利用同步机制实现读写锁的四种方法

转自:http://blog.csdn.net/ojshilu/article/details/25244389

对于某个临界资源的访问,读操作和写操作是要区别对待的。读操作可以多个线程同时进行,写操作必须互斥进行。

读写锁当已经被加了读锁时,其他的读模式锁请求仍然可以访问,但是写模式锁不能访问;当写模式锁加锁时,其他的请求都不能访问。


本文尝试用四种方法来完成读写锁的操作,都包含有写模式和读模式各自所要做的事情。

1、直接使用POSIX提供的读写锁

2、用条件变量实现读写锁

3、用互斥量实现读写锁

4、用信号量实现读写锁


直接使用读写锁

pthread中直接为我们提供的。
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include <pthread.h>      //多线程、读写锁所需头文件  
  2.   
  3. pthread_rwlock_t  rwlock = PTHREAD_RWLOCK_INITIALIZER; //定义和初始化读写锁  
  4.   
  5. 写模式:  
  6. pthread_rwlock_wrlock(&rwlock);     //加写锁  
  7. 写写写……  
  8. pthread_rwlock_unlock(&rwlock);     //解锁    
  9.   
  10.   
  11.   
  12. 读模式:  
  13. pthread_rwlock_rdlock(&rwlock);      //加读锁  
  14. 读读读……  
  15. pthread_rwlock_unlock(&rwlock);     //解锁   

用条件变量实现读写锁

这里用条件变量+互斥锁来实现。注意:条件变量必须和互斥锁一起使用,等待、释放的时候都需要加锁。
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include <pthread.h> //多线程、互斥锁所需头文件  
  2.   
  3. pthread_mutex_t  mutex = PTHREAD_MUTEX_INITIALIZER;      //定义和初始化互斥锁  
  4. pthread_cond_t  cond = PTHREAD_COND_INITIALIZER;       //定义和初始化条件变量  
  5.   
  6.   
  7. 写模式:  
  8. pthread_mutex_lock(&mutex);     //加锁  
  9. while(w != 0 || r > 0)  
  10. {  
  11.      pthread_cond_wait(&cond, &mutex);      //等待条件变量的成立  
  12. }  
  13. w = 1;  
  14.   
  15. pthread_mutex_unlock(&mutex);  
  16. 写写写……  
  17. pthread_mutex_lock(&mutex);  
  18. w = 0;  
  19. pthread_cond_broadcast(&cond);       //唤醒其他因条件变量而产生的阻塞  
  20. pthread_mutex_unlock(&mutex);    //解锁  
  21.   
  22.   
  23. 读模式:  
  24. pthread_mutex_lock(&mutex);       
  25. while(w != 0)  
  26. {  
  27.      pthread_cond_wait(&cond, &mutex);      //等待条件变量的成立  
  28. }  
  29. r++;  
  30. pthread_mutex_unlock(&mutex);  
  31. 读读读……  
  32. pthread_mutex_lock(&mutex);  
  33. r- -;  
  34. if(r == 0)  
  35.      pthread_cond_broadcast(&cond);       //唤醒其他因条件变量而产生的阻塞  
  36. pthread_mutex_unlock(&mutex);    //解锁  


用互斥锁实现读写锁

这里使用2个互斥锁+1个整型变量来实现。
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include <pthread.h> //多线程、互斥锁所需头文件  
  2. pthread_mutex_t r_mutex = PTHREAD_MUTEX_INITIALIZER;      //定义和初始化互斥锁  
  3. pthread_mutex_t w_mutex = PTHREAD_MUTEX_INITIALIZER;   
  4. int readers = 0;     //记录读者的个数  
  5.   
  6. 写模式:  
  7. pthread_mutex_lock(&w_mutex);  
  8. 写写写……  
  9. pthread_mutex_unlock(&w_mutex);  
  10.   
  11.   
  12. 读模式:  
  13. pthread_mutex_lock(&r_mutex);           
  14.   
  15. if(readers == 0)  
  16.      pthread_mutex_lock(&w_mutex);  
  17. readers++;  
  18. pthread_mutex_unlock(&r_mutex);   
  19. 读读读……  
  20. pthread_mutex_lock(&r_mutex);  
  21. readers- -;  
  22. if(reader == 0)  
  23.      pthread_mutex_unlock(&w_mutex);  
  24. pthread_mutex_unlock(&r_mutex);   

用信号量来实现读写锁

这里使用2个信号量+1个整型变量来实现。令信号量的初始数值为1,那么信号量的作用就和互斥量等价了。
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include <semaphore.h>     //线程信号量所需头文件  
  2.   
  3. sem_t r_sem;     //定义信号量  
  4. sem_init(&r_sem, 0, 1);     //初始化信号量   
  5.   
  6. sem_t w_sem;     //定义信号量  
  7. sem_init(&w_sem, 0, 1);     //初始化信号量    
  8. int readers = 0;  
  9.   
  10. 写模式:  
  11. sem_wait(&w_sem);  
  12. 写写写……  
  13. sem_post(&w_sem);  
  14.   
  15.   
  16. 读模式:  
  17. sem_wait(&r_sem);  
  18. if(readers == 0)  
  19.      sem_wait(&w_sem);  
  20. readers++;  
  21. sem_post(&r_sem);  
  22. 读读读……  
  23. sem_wait(&r_sem);  
  24. readers- -;  
  25. if(readers == 0)  
  26.      sem_post(&w_sem);  
  27. sem_post(&r_sem);  

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基于Windows同步机制的读者-写者问题的示例程序: ```cpp #include <windows.h> #include <stdio.h> // 读写锁 CRITICAL_SECTION g_csRead; CRITICAL_SECTION g_csWrite; // 读者数量和写者数量 int g_nReadCount = 0; int g_nWriteCount = 0; // 读者线程函数 DWORD WINAPI ReaderThread(LPVOID lpParam) { while (true) { EnterCriticalSection(&g_csRead); // 进入读锁 g_nReadCount++; // 增加读者数量 if (g_nReadCount == 1) // 如果是第一个读者 { EnterCriticalSection(&g_csWrite); // 进入写锁 } LeaveCriticalSection(&g_csRead); // 离开读锁 // 读取数据 printf("Reader read data: %d\n", *(int*)lpParam); EnterCriticalSection(&g_csRead); // 进入读锁 g_nReadCount--; // 减少读者数量 if (g_nReadCount == 0) // 如果是最后一个读者 { LeaveCriticalSection(&g_csWrite); // 离开写锁 } LeaveCriticalSection(&g_csRead); // 离开读锁 Sleep(1000); // 暂停1秒 } return 0; } // 写者线程函数 DWORD WINAPI WriterThread(LPVOID lpParam) { while (true) { EnterCriticalSection(&g_csWrite); // 进入写锁 g_nWriteCount++; // 增加写者数量 LeaveCriticalSection(&g_csWrite); // 离开写锁 // 写入数据 *(int*)lpParam = rand(); EnterCriticalSection(&g_csWrite); // 进入写锁 g_nWriteCount--; // 减少写者数量 LeaveCriticalSection(&g_csWrite); // 离开写锁 Sleep(1000); // 暂停1秒 } return 0; } int main() { InitializeCriticalSection(&g_csRead); InitializeCriticalSection(&g_csWrite); int nData = 0; // 创建10个读者线程和1个写者线程 HANDLE hReaderThreads[10]; for (int i = 0; i < 10; i++) { hReaderThreads[i] = CreateThread(NULL, 0, ReaderThread, &nData, 0, NULL); } HANDLE hWriterThread = CreateThread(NULL, 0, WriterThread, &nData, 0, NULL); // 等待所有线程结束 WaitForMultipleObjects(11, hReaderThreads, TRUE, INFINITE); WaitForSingleObject(hWriterThread, INFINITE); // 关闭句柄 for (int i = 0; i < 10; i++) { CloseHandle(hReaderThreads[i]); } CloseHandle(hWriterThread); DeleteCriticalSection(&g_csRead); DeleteCriticalSection(&g_csWrite); return 0; } ``` 在此程序中,我们使用了两个关键部分:读锁和写锁。读者线程和写者线程都需要进入这两个锁之一来访问共享数据。当读者线程进入读锁时,它需要增加读者数量,当它离开读锁时,它需要减少读者数量。当第一个读者线程进入读锁时,它需要进入写锁,以防止其他写者线程访问共享数据。当最后一个读者线程离开读锁时,它需要离开写锁以允许其他写者线程访问共享数据。当写者线程进入写锁时,它需要增加写者数量,在离开写锁时,它需要减少写者数量。 这个程序可以保证读者线程之间不会互相干扰,写者线程之间也不会互相干扰。同时,它还可以保证在任何时候只有一个写者线程可以访问共享数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值