linux 线程 读写锁

读写锁:🔴🟠🟡🟢🔵🟣🟤⚫⚪

  当有一个线程已经持有互斥锁时,互斥锁将所有试图进入临界区的线程都阻塞住。但是考虑一种情形,当前持有互斥锁的线程只是要读访问共享资源,而同时有其它几个线程也想读取这个共享资源,但是由于互斥锁的排他性,所有其他线程都无法获取锁,也就无法读访问共享资源了,但是实际上多个线程同时读访问共享资源并不会产生问题

  在对数据的读写操作中,更多的是读操作,写操作较少,例如对数据库数据的读写应用。为了满足当前能够允许多个读出,但只允许一个写入的需求,线程提供了读写锁来实现。

  读写锁的特点:

    🟢 如果有其他线程读数据,则允许其他线程执行读操作,但不允许写操作

    🟢 如果有其他线程写数据,则其他线程都不允许读、写操作

    🟢 写是独占的,写的优先级高

错误案例:可能读取9515  写入9514,未写入先读取(错误)。

复制代码
 1 /*
 2     读写锁的类型 pthread_rwlock_t
 3     int pthread_rwlock_init(pthread_rwlock_t * restrict rwlock, const pthread_rwlockattr_t * restrict attr);
 4     int pthread_rwlock_destroy(pthread_rwlock_t * rwlock);
 5     int pthread_rwlock_relock(pthread_rwlock_t * rwlock);
 6     int pthread_rwlock_tryrdlock(pthread_rwlock_t * rwlock);
 7     int pthread_rwlock_wrlock(pthread_rwlock_t * rwlock);
 8     int pthread_rwlock_trywrlock(pthread_rwlock_t * rwlock);
 9     int pthread_rwlock_unlock(pthread_rwlock_t * rwlock);
10     //案例:8个线程 操作同全局变量 
11     3个线程不定时写这个全局变量
12     其余5个线程不定时读这个全局变量
13 */
14 #include <stdio.h>
15 #include <unistd.h>
16 #include <pthread.h>
17 #include <string.h>
18 //创建一个共享数据
19 int num = 1;
20 void * writeNum(void * arg)
21 {
22     while(1)
23     {
24         num++;
25         printf("++write, tid : %ld,num: %d\n",pthread_self(),num);
26         usleep(100);
27     }
28     return NULL;
29 }
30 void * readNum(void * arg)
31 {
32     while(1)
33     {
34         printf("==read , tid : %ld, num: %d\n",pthread_self(),num);
35         usleep(100);
36     }
37     return NULL;
38 }
39 int main()
40 {
41     //创建3个写线程,5个读线程
42     pthread_t wtids[3],rtids[5];
43     for(int i = 0; i < 3;i++)
44     {
45         pthread_create(&wtids[i], NULL, writeNum, NULL);
46     }
47     for(int i = 0; i < 5;i++)
48     {
49         pthread_create(&rtids[i], NULL, readNum, NULL);
50     }
51     //设置线程分离
52     for(int i = 0; i < 3;i++)
53     {
54         pthread_detach(wtids[i]);
55     }
56     for(int i = 0; i < 5;i++)
57     {
58         pthread_detach(rtids[i]);
59     }
60     pthread_exit(NULL);//主线程退出,子线程继续运行
61     return 0;
62 }
复制代码

使用互斥锁可以解决但效率低:

复制代码
 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <pthread.h>
 4 #include <string.h>
 5 //创建一个共享数据
 6 int num = 1;
 7 pthread_mutex_t mutex;
 8 void * writeNum(void * arg)
 9 {
10     while(1)
11     {
12         pthread_mutex_lock(&mutex);
13         num++;
14         printf("++write, tid : %ld,num: %d\n",pthread_self(),num);
15         pthread_mutex_unlock(&mutex);
16         usleep(100);
17     }
18     return NULL;
19 }
20 void * readNum(void * arg)
21 {
22     while(1)
23     {
24         pthread_mutex_lock(&mutex);
25         printf("==read , tid : %ld, num: %d\n",pthread_self(),num);
26         pthread_mutex_unlock(&mutex);
27         usleep(100);
28     }
29     return NULL;
30 }
31 int main()
32 {
33     pthread_mutex_init(&mutex, NULL);
34     //创建3个写线程,5个读线程
35     pthread_t wtids[3],rtids[5];
36     for(int i = 0; i < 3;i++)
37     {
38         pthread_create(&wtids[i], NULL, writeNum, NULL);
39     }
40     for(int i = 0; i < 5;i++)
41     {
42         pthread_create(&rtids[i], NULL, readNum, NULL);
43     }
44     //设置线程分离
45     for(int i = 0; i < 3;i++)
46     {
47         pthread_detach(wtids[i]);
48     }
49     for(int i = 0; i < 5;i++)
50     {
51         pthread_detach(rtids[i]);
52     }
53     pthread_exit(NULL);//主线程退出,子线程继续运行
54 
55     pthread_mutex_destroy(&mutex);
56     return 0;
57 }
复制代码

读写锁:

复制代码
 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <pthread.h>
 4 #include <string.h>
 5 //创建一个共享数据
 6 int num = 1;
 7 pthread_rwlock_t  rwlock;
 8 void * writeNum(void * arg)
 9 {
10     while(1)
11     {
12         pthread_rwlock_wrlock(&rwlock);
13         num++;
14         printf("++write, tid : %ld,num: %d\n",pthread_self(),num);
15         pthread_rwlock_unlock(&rwlock);
16         usleep(100);
17     }
18     return NULL;
19 }
20 void * readNum(void * arg)
21 {
22     while(1)
23     {
24         pthread_rwlock_rdlock(&rwlock);
25         printf("==read , tid : %ld, num: %d\n",pthread_self(),num);
26         pthread_rwlock_unlock(&rwlock);
27         usleep(100);
28     }
29     return NULL;
30 }
31 int main()
32 {   
33     pthread_rwlock_init(&rwlock,NULL);
34     //创建3个写线程,5个读线程
35     pthread_t wtids[3],rtids[5];
36     for(int i = 0; i < 3;i++)
37     {
38         pthread_create(&wtids[i], NULL, writeNum, NULL);
39     }
40     for(int i = 0; i < 5;i++)
41     {
42         pthread_create(&rtids[i], NULL, readNum, NULL);
43     }
44     //设置线程分离
45     for(int i = 0; i < 3;i++)
46     {
47         pthread_detach(wtids[i]);
48     }
49     for(int i = 0; i < 5;i++)
50     {
51         pthread_detach(rtids[i]);
52     }
53     pthread_exit(NULL);//主线程退出,子线程继续运行
54 
55     pthread_rwlock_destroy(&rwlock);
56     return 0;
57 }
复制代码

posted on   廿陆  阅读(24)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示