博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
互斥锁的robust属性的介绍和使用
阅读量:4359 次
发布时间:2019-06-07

本文共 7596 字,大约阅读时间需要 25 分钟。

一个具体的场景:在多线程中,当一个线程获得锁之后异常退出后,应该怎么处理?

方案一 使用锁的robust特性

简单地讲,就是当拥有这个锁的线程挂了后,下一个尝试去获得锁的线程会得到EOWNWERDEAD的返回值,新的拥有者应该再去调用pthread_mutex_consistent_np()来保持锁状态的一致性,并解锁。

直接上代码看示例:

1 /*================================================================  2  *   Copyright (C) 2019 Ltd. All rights reserved.  3  *     4  *   File Name :robust_mutex.c  5  *   Author    :Hamilton  6  *   Date      :2019-07-30  7  *   Descriptor:  8  *  9  ================================================================*/ 10  11 #include 
12 #include
13 #include
14 #include
15 #include
16 17 #define handle_error_en(en, msg) \ 18 do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0) 19 20 static pthread_mutex_t mtx; 21 22 static void *original_owner_thread(void *ptr) 23 { 24 printf("\n[original owner] Setting lock...\n"); 25 pthread_mutex_lock(&mtx); 26 printf("[original owner] Locked. Now exiting without unlocking.\n"); 27 pthread_exit(NULL); 28 } 29 static void *bad_thread(void *ptr) 30 { 31 printf("\n[bad owner] Setting lock...\n"); 32 pthread_mutex_lock(&mtx); 33 printf("[bad owner] Locked. Now exiting without unlocking.\n"); 34 pthread_exit(NULL); 35 } 36 static void *second_thread(void *ptr) 37 { 38 int i = 5; 39 40 while (i--) 41 { 42 int s = pthread_mutex_lock(&mtx); 43 44 if (s == EOWNERDEAD) 45 { 46 printf("\n[second thread] pthread_mutex_lock() returned EOWNERDEAD\n"); 47 48 printf("[second thread] Now make the mutex consistent\n"); 49 s = pthread_mutex_consistent(&mtx); 50 if (s != 0) 51 handle_error_en(s, "pthread_mutex_consistent"); 52 53 printf("[second thread] Mutex is now consistent; unlocking\n"); 54 s = pthread_mutex_unlock(&mtx); 55 if (s != 0) 56 handle_error_en(s, "pthread_mutex_unlock"); 57 58 } 59 else if (s < 0) 60 { 61 printf("\n[second thread] pthread_mutex_lock() unexpectedly failed\n"); 62 handle_error_en(s, "pthread_mutex_lock"); 63 } 64 else 65 { 66 printf("\n[second thread] pthread_mutex_lock success.\n"); 67 printf("do somthing.... \n"); 68 s = pthread_mutex_unlock(&mtx); 69 if (s != 0) 70 handle_error_en(s, "pthread_mutex_unlock"); 71 } 72 sleep(1); 73 } 74 75 pthread_exit(NULL); 76 } 77 78 int main(int argc, char *argv[]) 79 { 80 pthread_t thr; 81 pthread_mutexattr_t attr; 82 int s; 83 84 pthread_mutexattr_init(&attr); 85 /* initialize the attributes object */ 86 pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST); 87 /* set robustness */ 88 89 pthread_mutex_init(&mtx, &attr); /* initialize the mutex */ 90 91 pthread_create(&thr, NULL, original_owner_thread, NULL); 92 93 sleep(1); 94 pthread_create(&thr, NULL, second_thread, NULL); 95 sleep(1); 96 pthread_create(&thr, NULL, bad_thread, NULL); 97 98 /* "original_owner_thread" should have exited by now */ 99 100 int i = 5;101 while(i--)102 {103 s = pthread_mutex_lock(&mtx);104 105 if (s == EOWNERDEAD) 106 {107 printf("\n[main thread] pthread_mutex_lock() returned EOWNERDEAD\n");108 109 printf("[main thread] Now make the mutex consistent\n");110 s = pthread_mutex_consistent(&mtx);111 if (s != 0)112 handle_error_en(s, "pthread_mutex_consistent");113 114 printf("[main thread] Mutex is now consistent; unlocking\n");115 s = pthread_mutex_unlock(&mtx);116 if (s != 0)117 handle_error_en(s, "pthread_mutex_unlock");118 119 } 120 else if (s < 0)121 {122 printf("\n[main thread] pthread_mutex_lock() unexpectedly failed\n");123 handle_error_en(s, "pthread_mutex_lock");124 }125 else 126 {127 printf("\n[main thread] pthread_mutex_lock success.\n");128 printf("do somthing.... \n");129 s = pthread_mutex_unlock(&mtx);130 if (s != 0)131 handle_error_en(s, "pthread_mutex_unlock");132 }133 134 sleep(1);135 }136 exit(EXIT_SUCCESS);137 }

 

示例中总共包含四个线程,original_owner_thread() 和 bad_thread() 两个线程获得锁后立马退出不释放,其它两个线程main thread 及 second_thread() 轮流抢占锁,并对锁的异常进行恢复处理,看下打印结果:

是不是很简单,通过设置robust特性,并在每次获取锁时判断锁的异常状态,便能很好的处理锁异常退出的情况。

关于锁的robust特性及consistent设定,可参考以下更多资料:

本文示例改编自:

 

后记:再看看进程间有没有类似的机制,但是google并没有找到相关介绍,便想看看pthreas_mutex_lock这套机制在process下工作是否正常,先看示例代码:

1 /*================================================================  2  *   Copyright (C) 2019 Ltd. All rights reserved.  3  *     4  *   File Name :robust_mutex.c  5  *   Author    :Hamilton  6  *   Date      :2019-07-30  7  *   Descriptor:  8  *  9  ================================================================*/ 10  11 #include 
12 #include
13 #include
14 #include
15 #include
16 #include
17 #include
18 #include
19 #include
20 21 #define SHM_NAME "fasdfasfasfas" 22 23 24 #define handle_error_en(en, msg) \ 25 do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0) 26 27 static pthread_mutex_t *mtx; 28 static int fd_shm; 29 30 void shm_mutex_init(pthread_mutex_t **mutex) 31 { 32 pthread_mutexattr_t attr; 33 34 pthread_mutexattr_init(&attr); 35 /* initialize the attributes object */ 36 pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST); 37 /* set robustness */ 38 39 // Get shared memory 40 if ((fd_shm = shm_open (SHM_NAME, O_RDWR | O_CREAT, 0660)) == -1) 41 perror ("shm_open"); 42 43 if (ftruncate (fd_shm, sizeof (pthread_mutex_t)) == -1) 44 perror ("ftruncate"); 45 46 if ((*mutex = mmap (NULL, sizeof (pthread_mutex_t), PROT_READ | PROT_WRITE, MAP_SHARED, 47 fd_shm, 0)) == MAP_FAILED) 48 perror ("mmap"); 49 50 pthread_mutex_init(*mutex, &attr); /* initialize the mutex */ 51 } 52 int main(int argc, char *argv[]) 53 { 54 int s; 55 56 shm_mutex_init(&mtx); 57 58 if ((s = fork()) < 0) 59 { 60 perror("fork."); 61 } 62 else if (s == 0) // child 63 { 64 sleep(1); 65 printf("\n[bad owner] Setting lock...\n"); 66 pthread_mutex_lock(mtx); 67 printf("[bad owner] Locked. Now exiting without unlocking.\n"); 68 } 69 else 70 { 71 int i = 5; 72 while(i--) 73 { 74 s = pthread_mutex_lock(mtx); 75 76 if (s == EOWNERDEAD) 77 { 78 printf("\n[main thread] pthread_mutex_lock() returned EOWNERDEAD\n"); 79 80 printf("[main thread] Now make the mutex consistent\n"); 81 s = pthread_mutex_consistent(mtx); 82 if (s != 0) 83 handle_error_en(s, "pthread_mutex_consistent"); 84 85 printf("[main thread] Mutex is now consistent; unlocking\n"); 86 s = pthread_mutex_unlock(mtx); 87 if (s != 0) 88 handle_error_en(s, "pthread_mutex_unlock"); 89 90 } 91 else if (s < 0) 92 { 93 printf("\n[main thread] pthread_mutex_lock() unexpectedly failed\n"); 94 handle_error_en(s, "pthread_mutex_lock"); 95 } 96 else 97 { 98 printf("\n[main thread] pthread_mutex_lock success.\n"); 99 printf("do somthing.... \n");100 s = pthread_mutex_unlock(mtx);101 if (s != 0)102 handle_error_en(s, "pthread_mutex_unlock");103 }104 105 sleep(1);106 }107 }108 exit(EXIT_SUCCESS);109 }

 

 编译执行下看看:

进程间通信的锁得放在共享内存中,编译运行OK,也能正常工作。

 

转载于:https://www.cnblogs.com/miaoxiong/p/11301910.html

你可能感兴趣的文章
MVC4网站发布到windows server 2003服务器
查看>>
《构建之法》读书笔记
查看>>
细说多线程(上)
查看>>
最长公共子序列(不连续)
查看>>
微服务:Java EE的拯救者还是掘墓人?
查看>>
如何在Centos里面,把.net core程序设为开机自启动
查看>>
1920*1080pc端适配
查看>>
Nutch系列1:简介
查看>>
前端UI框架选择区别对比推荐
查看>>
栈 队列 和 双向队列
查看>>
从垃圾回收看闭包
查看>>
Intel Core Microarchitecture Pipeline
查看>>
如何去除交叉表的子行(列)的小计?
查看>>
Web字体(链接)嵌入
查看>>
switch… case 语句的用法
查看>>
day07补充-数据类型总结及拷贝
查看>>
语言、数据和运算符
查看>>
正则表达式30分钟入门教程
查看>>
sqlserver try catch·
查看>>
怎么在三维世界里叙述五维故事
查看>>