当前位置:网站首页>线程同步之读写锁
线程同步之读写锁
2022-06-26 03:56:00 【StudyWinter】
与互斥量类似,但读写锁允许更高的并行性。其特性为: 写独占,读共享。
1 读写锁状态
特别强调: 读写锁只有一把, 但其具备两种状态:
1 读模式下加锁状态 (读锁);
2 写模式下加锁状态 (写锁) 。
2 读写锁特性
1 读写锁是“写模式加锁”时, 解锁前,所有对该锁加锁的线程都会被阻塞;
2 读写锁是“读模式加锁”时, 如果线程以读模式对其加锁会成功;如果线程以写模式加锁会阻塞;
3 读写锁是“读模式加锁”时, 既有试图以写模式加锁的线程,也有试图以读模式加锁的线程。那么读写锁会阻塞随后的读模式锁请求。优先满足写模式锁。 读锁、写锁并行阻塞, 写锁优先级高 。
读写锁也叫共享-独占锁。当读写锁以读模式锁住时,它是以共享模式锁住的;当它以写模式锁住时,它是以独占模式锁住的。 写独占、读共享。读写锁非常适合于对数据结构读的次数远大于写的情况。
主要函数
pthread_rwlock_t rwlock;
pthread_rwlock_init(&rwlock, NULL);
pthread_rwlock_rdlock(&rwlock); // try
pthread_rwlock_wrlock(&rwlock); // try
pthread_rwlock_unlock(&rwlock);
pthread_rwlock_destroy(&rwlock);
以上函数都是成功返回0,失败返回错误号。
(1)pthread_rwlock_init 函数
初始化一把读写锁
pthread_rwlock_t rwlock;
// 方法1
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
const pthread_rwlockattr_t *restrict attr);
// 参 2: attr 表读写锁属性,通常使用默认属性, 传 NULL 即可
// 方法2
rwlock = PTHREAD_RWLOCK_INITIALIZER;
(2)pthread_rwlock_destroy 函数
销毁一把读写锁
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
(3)pthread_rwlock_rdlock 函数
以读方式请求读写锁。(常简称为:请求读锁)
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
(4)pthread_rwlock_wrlock 函数
以写方式请求读写锁。(常简称为:请求写锁)
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
(5)pthread_rwlock_unlock 函数
解锁
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
(6)pthread_rwlock_tryrdlock 函数
非阻塞以读方式请求读写锁(非阻塞请求读锁)
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
(7)pthread_rwlock_trywrlock函数
非阻塞以写方式请求读写锁(非阻塞请求写锁)
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
3 两种死锁
是使用锁不恰当导致的现象:
1. 对一个锁反复lock。
2. 两个线程,各自持有一把锁,请求另一把。
4 读写锁案例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
// 全局共享资源
int counter;
// 全局读写锁,初始化
pthread_rwlock_t rwlock;
// rwlock = PTHREAD_RWLOCK_INITIALIZER;
// 任务:3个线程不同时写同一资源,5个线程不同时读同一资源
// 写
void *do_write(void *arg)
{
int t = 0;
int i = (int)arg;
int res = 0;
while (1)
{
// 加锁,写锁独占
res = pthread_rwlock_wrlock(&rwlock);
if (res != 0)
{
fprintf(stderr, "pthread_rwlock_wrlock error:%s\n", strerror(res));
exit(1);
}
t = counter;
usleep(10000);
// 修改就是写
printf("------write:%d, %lu, counter = %d, ++counter = %d\n", i, pthread_self(), t, ++counter);
// 解锁
res = pthread_rwlock_unlock(&rwlock);
if (res != 0)
{
fprintf(stderr, "pthread_rwlock_unlock error:%s\n", strerror(res));
exit(1);
}
usleep(10000);
}
return NULL;
}
// 读
void *do_read(void *arg)
{
int res = 0;
int i = (int)arg;
while (1) {
// 加锁,读共享
res = pthread_rwlock_rdlock(&rwlock);
if (res != 0)
{
fprintf(stderr, "pthread_rwlock_rdlock error:%s\n", strerror(res));
exit(1);
}
usleep(10000);
// 修改就是写
printf("==========================================read:%d, %lu, counter = %d\n", i, pthread_self(), counter);
// 解锁
res = pthread_rwlock_unlock(&rwlock);
if (res != 0)
{
fprintf(stderr, "pthread_rwlock_unlock error:%s\n", strerror(res));
exit(1);
}
usleep(10000);
}
return NULL;
}
int main(int argc, char **argv)
{
int i;
// 8个线程
pthread_t tid[8];
// 初始化读写锁
int res = pthread_rwlock_init(&rwlock, NULL);
if (res != 0)
{
fprintf(stderr, "pthread_rwlock_init error:%s\n", strerror(res));
exit(1);
}
// 初始化线程
// 写线程
for (i = 0; i < 3; i++)
{
res = pthread_create(&tid[i], NULL, do_write, (void *)i);
if (res != 0)
{
fprintf(stderr, "pthread_create write error:%s\n", strerror(res));
exit(1);
}
}
// 读线程
for (i = 3; i < 8; i++)
{
res = pthread_create(&tid[i], NULL, do_read, (void *)i);
if (res != 0)
{
fprintf(stderr, "pthread_create read error:%s\n", strerror(res));
exit(1);
}
}
// 回收子线程
for (i = 0; i < 8; i++)
{
res = pthread_join(tid[i], NULL);
if (res != 0)
{
fprintf(stderr, "pthread_join error:%s\n", strerror(res));
exit(1);
}
}
// 销毁读写锁
res = pthread_rwlock_destroy(&rwlock);
if (res != 0)
{
fprintf(stderr, "pthread_join error:%s\n", strerror(res));
exit(1);
}
return 0;
}
执行
程序输出飞快,随便截个图,如上图。
由于读共享,写独占。写锁优先级高。前面5个read一定先于后面的write到达的,不然write会抢到锁先进行写操作。
边栏推荐
- Matplotlib multi line chart, dot scatter chart
- (15) Blender source code analysis flash window display menu function
- Webrtc series - 7-ice supplement of network transmission preference and priority
- Mybatis的引入问题invalid
- QPS的概念和实现
- Non H5 end of uni app, regional setting of status bar on the top of mobile phone
- I/o virtualization technology - vfio
- 刷题记录Day01
- bubble sort
- What's wrong with connecting MySQL database with eclipse and then the words in the figure appear
猜你喜欢
Oracle技术分享 oracle 19.14升级19.15
An error occurred using the connection to database 'on server' 10.28.253.2‘
Uni app custom navigation bar component
C # knowledge structure
Unity移动端游戏性能优化简谱之 以引擎模块为划分的CPU耗时调优
1.基础关
MapReduce执行原理记录
Use soapUI to access the corresponding ESB project
When the tiflash function is pushed down, it must be known that it will become a tiflash contributor in ten minutes
Matplotlib multi line chart, dot scatter chart
随机推荐
1. foundation closing
神经网络学习小记录71——Tensorflow2 使用Google Colab进行深度学习
After a test of 25K bytes, I really saw the basic ceiling
三元损失英文版
【掘金运营套路揭露】真心被掘金的套路....
Sqlitestudio download address
ABP framework Practice Series (II) - Introduction to domain layer
816. fuzzy coordinates
智能制造学习记录片和书籍
MapReduce execution principle record
I/o virtualization technology - UIO framework
Chrome page recording and playback function
Three level menu applet
开源!ViTAE模型再刷世界第一:COCO人体姿态估计新模型取得最高精度81.1AP
Slide the menu of uni app custom components left and right and click switch to select and display in the middle
Oracle technology sharing Oracle 19.14 upgrade 19.15
asp.net网页选择身份进行登录的简单代码,asp连接数据库,使用asp:Panel、asp:DropDownList控件
Question brushing record day01
Camera-CreateCaptureSession
Matplotlib multi line chart, dot scatter chart