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

方案一 使用锁的robust特性

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

直接上代码看示例:

 /*================================================================
* Copyright (C) 2019 Ltd. All rights reserved.
*
* File Name :robust_mutex.c
* Author :Hamilton
* Date :2019-07-30
* Descriptor:
*
================================================================*/ #include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h> #define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while () static pthread_mutex_t mtx; static void *original_owner_thread(void *ptr)
{
printf("\n[original owner] Setting lock...\n");
pthread_mutex_lock(&mtx);
printf("[original owner] Locked. Now exiting without unlocking.\n");
pthread_exit(NULL);
}
static void *bad_thread(void *ptr)
{
printf("\n[bad owner] Setting lock...\n");
pthread_mutex_lock(&mtx);
printf("[bad owner] Locked. Now exiting without unlocking.\n");
pthread_exit(NULL);
}
static void *second_thread(void *ptr)
{
int i = ; while (i--)
{
int s = pthread_mutex_lock(&mtx); if (s == EOWNERDEAD)
{
printf("\n[second thread] pthread_mutex_lock() returned EOWNERDEAD\n"); printf("[second thread] Now make the mutex consistent\n");
s = pthread_mutex_consistent(&mtx);
if (s != )
handle_error_en(s, "pthread_mutex_consistent"); printf("[second thread] Mutex is now consistent; unlocking\n");
s = pthread_mutex_unlock(&mtx);
if (s != )
handle_error_en(s, "pthread_mutex_unlock"); }
else if (s < )
{
printf("\n[second thread] pthread_mutex_lock() unexpectedly failed\n");
handle_error_en(s, "pthread_mutex_lock");
}
else
{
printf("\n[second thread] pthread_mutex_lock success.\n");
printf("do somthing.... \n");
s = pthread_mutex_unlock(&mtx);
if (s != )
handle_error_en(s, "pthread_mutex_unlock");
}
sleep();
} pthread_exit(NULL);
} int main(int argc, char *argv[])
{
pthread_t thr;
pthread_mutexattr_t attr;
int s; pthread_mutexattr_init(&attr);
/* initialize the attributes object */
pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST);
/* set robustness */ pthread_mutex_init(&mtx, &attr); /* initialize the mutex */ pthread_create(&thr, NULL, original_owner_thread, NULL); sleep();
pthread_create(&thr, NULL, second_thread, NULL);
sleep();
pthread_create(&thr, NULL, bad_thread, NULL); /* "original_owner_thread" should have exited by now */ int i = ;
while(i--)
{
s = pthread_mutex_lock(&mtx); if (s == EOWNERDEAD)
{
printf("\n[main thread] pthread_mutex_lock() returned EOWNERDEAD\n"); printf("[main thread] Now make the mutex consistent\n");
s = pthread_mutex_consistent(&mtx);
if (s != )
handle_error_en(s, "pthread_mutex_consistent"); printf("[main thread] Mutex is now consistent; unlocking\n");
s = pthread_mutex_unlock(&mtx);
if (s != )
handle_error_en(s, "pthread_mutex_unlock"); }
else if (s < )
{
printf("\n[main thread] pthread_mutex_lock() unexpectedly failed\n");
handle_error_en(s, "pthread_mutex_lock");
}
else
{
printf("\n[main thread] pthread_mutex_lock success.\n");
printf("do somthing.... \n");
s = pthread_mutex_unlock(&mtx);
if (s != )
handle_error_en(s, "pthread_mutex_unlock");
} sleep();
}
exit(EXIT_SUCCESS);
}

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

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

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

https://docs.oracle.com/cd/E19455-01/806-5257/6je9h032m/index.html

http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_consistent.html

本文示例改编自:http://manpages.ubuntu.com/manpages/bionic/man3/pthread_mutexattr_setrobust.3.html

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

 /*================================================================
* Copyright (C) 2019 Ltd. All rights reserved.
*
* File Name :robust_mutex.c
* Author :Hamilton
* Date :2019-07-30
* Descriptor:
*
================================================================*/ #include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h> #define SHM_NAME "fasdfasfasfas" #define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while () static pthread_mutex_t *mtx;
static int fd_shm; void shm_mutex_init(pthread_mutex_t **mutex)
{
pthread_mutexattr_t attr; pthread_mutexattr_init(&attr);
/* initialize the attributes object */
pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST);
/* set robustness */ // Get shared memory
if ((fd_shm = shm_open (SHM_NAME, O_RDWR | O_CREAT, )) == -)
perror ("shm_open"); if (ftruncate (fd_shm, sizeof (pthread_mutex_t)) == -)
perror ("ftruncate"); if ((*mutex = mmap (NULL, sizeof (pthread_mutex_t), PROT_READ | PROT_WRITE, MAP_SHARED,
fd_shm, )) == MAP_FAILED)
perror ("mmap"); pthread_mutex_init(*mutex, &attr); /* initialize the mutex */
}
int main(int argc, char *argv[])
{
int s; shm_mutex_init(&mtx); if ((s = fork()) < )
{
perror("fork.");
}
else if (s == ) // child
{
sleep();
printf("\n[bad owner] Setting lock...\n");
pthread_mutex_lock(mtx);
printf("[bad owner] Locked. Now exiting without unlocking.\n");
}
else
{
int i = ;
while(i--)
{
s = pthread_mutex_lock(mtx); if (s == EOWNERDEAD)
{
printf("\n[main thread] pthread_mutex_lock() returned EOWNERDEAD\n"); printf("[main thread] Now make the mutex consistent\n");
s = pthread_mutex_consistent(mtx);
if (s != )
handle_error_en(s, "pthread_mutex_consistent"); printf("[main thread] Mutex is now consistent; unlocking\n");
s = pthread_mutex_unlock(mtx);
if (s != )
handle_error_en(s, "pthread_mutex_unlock"); }
else if (s < )
{
printf("\n[main thread] pthread_mutex_lock() unexpectedly failed\n");
handle_error_en(s, "pthread_mutex_lock");
}
else
{
printf("\n[main thread] pthread_mutex_lock success.\n");
printf("do somthing.... \n");
s = pthread_mutex_unlock(mtx);
if (s != )
handle_error_en(s, "pthread_mutex_unlock");
} sleep();
}
}
exit(EXIT_SUCCESS);
}

编译执行下看看:

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

互斥锁的robust属性的介绍和使用的更多相关文章

  1. linux c学习笔记----互斥锁属性

    转自:http://lobert.iteye.com/blog/1762844 互斥锁属性 使用互斥锁(互斥)可以使线程按顺序执行.通常,互斥锁通过确保一次只有一个线程执行代码的临界段来同步多个线程. ...

  2. 四十、Linux 线程——互斥锁和读写锁

    40.1 互斥锁 40.1.1 介绍 互斥锁(mutex)是一种简单的加锁的方法来控制对共享资源的访问. 在同一时刻只能有一个线程掌握某个互斥锁,拥有上锁状态的线程能够对共享资源进行访问. 若其他线程 ...

  3. 【Linux C 多线程编程】互斥锁与条件变量

    一.互斥锁 互斥量从本质上说就是一把锁, 提供对共享资源的保护访问. 1) 初始化: 在Linux下, 线程的互斥量数据类型是pthread_mutex_t. 在使用前, 要对它进行初始化: 对于静态 ...

  4. 【转载】同步和互斥的POSIX支持(互斥锁,条件变量,自旋锁)

    上篇文章也蛮好,线程同步之条件变量与互斥锁的结合: http://www.cnblogs.com/charlesblc/p/6143397.html   现在有这篇文章: http://blog.cs ...

  5. 互斥锁属性PTHREAD_MUTEX_RECURSIVE

    四.互斥锁属性 线程和线程的同步对象(互斥量,读写锁,条件变量)都具有属性.在修改属性前都需要对该结构进行初始化.使用后要把该结构回收.我们用pthread_ mutexattr_init函数对pth ...

  6. 创建进程,join方法,进程对象相关属性和方法,僵尸进程和孤儿进程,守护进程,互斥锁

    创建进程 在python中提供了一个multiprocessing模块可以帮助我们使用多进程解决问题.在multiprocessing 模块中有一个类Process. from multiproces ...

  7. Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等

    Java 中15种锁的介绍 Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等,在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类 ...

  8. 8.12 day31 进程间通信 Queue队列使用 生产者消费者模型 线程理论 创建及对象属性方法 线程互斥锁 守护线程

    进程补充 进程通信 要想实现进程间通信,可以用管道或者队列 队列比管道更好用(队列自带管道和锁) 管道和队列的共同特点:数据只有一份,取完就没了 无法重复获取用一份数据 队列特点:先进先出 堆栈特点: ...

  9. Java 种15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁等等…

    Java 中15种锁的介绍 1,在读很多并发文章中,会提及各种各样的锁,如公平锁,乐观锁,下面是对各种锁的总结归纳: 公平锁/非公平锁 可重入锁/不可重入锁 独享锁/共享锁 互斥锁/读写锁 乐观锁/悲 ...

随机推荐

  1. 【BigData】Java基础_方法的定义与使用

    1.概念 Java语言中的“方法”(Method)在其他语言当中也可能被称为“函数”(Function).对于一些复杂的代码逻辑,如果希望重复使用这些代码,并且做到“随时任意使用”,那么就可以将这些代 ...

  2. http 默认端口

    80是http协议的默认端口,是在输入网站的时候其实浏览器(非IE)已经帮你输入协议了,所以你输入http://baidu.com,其实是访问http://baidu.com:80.而8080,一般用 ...

  3. Leetcode 1262. 可被三整除的最大和

    题目:给你一个整数数组 nums,请你找出并返回能被三整除的元素最大和. 示例 1: 输入:nums = [3,6,5,1,8] 输出:18 解释:选出数字 3, 6, 1 和 8,它们的和是 18( ...

  4. Python 中如何判断 list 中是否包含某个元素

    在python中判断 list 中是否包含某个元素: ——可以通过in和not in关键字来判读 例如: abcList=['a','b','c',1,2,3] if 'a' in abcList: ...

  5. Maven 教程(5)— Maven目录结构及常用命令说明

    原文地址:https://blog.csdn.net/liupeifeng3514/article/details/79543159 1.Maven目录结构说明 Maven总体目录结构如下图: bin ...

  6. Python【每日一问】29

    问: [基础题]:给一个不多于 5 位的正整数,要求:一.求它是几位数,二.逆序印出各位数字[提高题]:某个公司采用公用电话传递数据,数据是四位的整数,在传递过程中是加密的,加密规则如下:每位数字都加 ...

  7. 一文让你彻底理解准确率,精准率,召回率,真正率,假正率,ROC/AUC

    参考资料:https://zhuanlan.zhihu.com/p/46714763 ROC/AUC作为机器学习的评估指标非常重要,也是面试中经常出现的问题(80%都会问到).其实,理解它并不是非常难 ...

  8. 模拟 + 打表 --- Emag eht htiw Em Pleh

    Emag eht htiw Em Pleh Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2578   Accepted: ...

  9. Java多线程编程(2)--多线程编程中的挑战

    一.串行.并发和并行   为了更清楚地解释这三个概念,我们来举一个例子.假设我们有A.B.C三项工作要做,那么我们有以下三种方式来完成这些工作:   第一种方式,先开始做工作A,完成之后再开始做工作B ...

  10. CentOS修改ulimit

    一.概述 查看limit配置 # ulimit -a core data seg size (kbytes, -d) unlimited scheduling priority (-e) file s ...