Linux下使用原子锁实现线程同步

http://blog.csdn.net/it_way/article/details/23061301


以下内容仅做为学习笔记使用,主要分析学习过程中遇到的问题。如有什么理解不到位的地方,还请多多指教!

原子锁是linux内核同步的一种机制,下面将其应用到线程同步中来。贴上代码

[cpp]  view plain copy
  1. #include <alsa/iatomic.h>  
  2. #include <pthread.h>  
  3. #include <stdio.h>  
  4.   
  5. // 定义一个原子变量  
  6. static atomic_t g_atomic = ATOMIC_INIT(1);  
  7. // 定义共享资源  
  8. static volatile int g_i = 0;  
  9.   
  10. /* 定义线程处理函数 */  
  11. //#define atomic_dec_and_test(g_atomic) 1   
  12. void *thr1_handle(void *arg)  
  13. {  
  14.     while (1) {  
  15.         if (atomic_dec_and_test(&g_atomic)) {  
  16.             printf("in thread %lu g_i = %d\n", pthread_self(), ++g_i);  
  17.         }  
  18.         atomic_inc(&g_atomic);  
  19.         sleep(1);  
  20.     }  
  21.   
  22.     return NULL;     
  23. }  
  24.   
  25. void *thr2_handle(void *arg)  
  26. {  
  27.     while (1) {  
  28.         if (atomic_dec_and_test(&g_atomic)) {  
  29.             printf("in thread %lu g_i = %d\n", pthread_self(), --g_i);  
  30.         }  
  31.         atomic_inc(&g_atomic);  
  32.         sleep(1);  
  33.     }  
  34.     return NULL;     
  35. }  
  36.   
  37.   
  38. /* 主函数 */  
  39. int main()  
  40. {  
  41.     pthread_t tid1, tid2;  
  42.     if (pthread_create(&tid1, NULL, thr1_handle, NULL) != 0) {  
  43.         fprintf(stderr, "create thread1 failed!\n");  
  44.         return 1;  
  45.     }  
  46.     if (pthread_create(&tid2, NULL, thr2_handle, NULL) != 0) {  
  47.         fprintf(stderr, "create thread2 failed!\n");  
  48.         return 2;  
  49.     }  
  50.   
  51.     pthread_join(tid1, NULL);  
  52.     pthread_join(tid2, NULL);  
  53.   
  54.     return 0;  
  55. }  

不错,这里用 atomic 做了同步,程序如预期输出:

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. in thread 3076184896 g_i = 1  
  2. in thread 3067792192 g_i = 0  
  3. in thread 3076184896 g_i = 1  
  4. in thread 3067792192 g_i = 0  
  5. in thread 3076184896 g_i = 1  
  6. in thread 3067792192 g_i = 0  
  7. in thread 3076184896 g_i = 1  
  8. in thread 3067792192 g_i = 0  
  9. in thread 3076184896 g_i = 1  
  10. in thread 3067792192 g_i = 0  
  11. in thread 3076184896 g_i = 1  
  12. in thread 3067792192 g_i = 0  
  13. in thread 3076184896 g_i = 1  
  14. in thread 3067792192 g_i = 0  
  15. in thread 3076184896 g_i = 1  
没有任何问题。

但是这里最应该记住的是,如果不同不产生的后果。

如果将上面的

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //#define atomic_dec_and_test(g_atomic) 1  
注释打开,即不让 atomic 来提供同步工作,那么程序的结果是混乱的。 如下:

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. in thread 3075713856 g_i = 1             
  2. in thread 3067321152 g_i = 0             
  3. in thread 3067321152 g_i = -1             
  4. in thread 3075713856 g_i = 1             
  5. in thread 3067321152 g_i = 0             
  6. in thread 3075713856 g_i = 1             
  7. in thread 3075713856 g_i = 2        
  8. in thread 3067321152 g_i = 0             

在上面这种混乱的输出,源于 ++/-- 并非原子操作,在执行 ++/-- 的操作过程中,很可能发生线程切换,这是上一线程所做的修改还没来得及保存到内存,这样就出现数据的不同步。


本文参考了网上资源:

http://www.netfoucs.com/fenglifeng1987/article/details/8172975 这里讲述了 atomic 的相关API

http://www.linuxidc.com/Linux/2011-06/37402.htm  这里讲述了在 2.6.18 内核后删除atomic,并提供了一个替代品


文章最后感谢论坛网友的分析:

http://bbs.chinaunix.net/thread-4134133-1-1.html


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值