Linux线程浅析[线程的同步和互斥之线程死锁,线程与信号的关系]

时间:2021-01-16 23:24:17

Linux线程浅析[线程的同步和互斥之线程死锁,线程与信号的关系]

  1. 线程死锁
  2. 线程与信号

记得以前在学习java线程的时候,也会接触死锁,当时不断强调锁千万不要不能去做嵌套,不然容易一个线程在执行的时候所需要的锁被别的线程持有了,而别的线程执行的时候,它的锁又被第一个线程持有,这种相互持有锁却释放不了的这样的一种情况

线程死锁

什么是死锁?

两个线程试图同时占用两个资源,并按不同的次序锁定相应的共享资源

解决方式

1:按相同的次序锁定相应的共享资源
2:pthread_mutex_trylock(),它是函数pthread_mutex_lock()的非阻塞函数

打造属于自己的死锁:

/*
* ===========================================================================
*
* Filename: pthread_dead_lock.c
* Description:
* Version: 1.0
* Created: 2017年04月04日 21时30分44秒
* Revision: none
* Compiler: gcc
* Author: (),
* Company:
*
* ===========================================================================
*/


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<pthread.h>

typedef struct{
int res;
pthread_mutex_t mutex_one;
}ArgvType1;

typedef struct{
int res;
pthread_mutex_t mutex_two;
}ArgvType2;

typedef struct{
ArgvType1* type1;
ArgvType2* type2;
}Argv;


void* one_th(void* argv){
Argv* argv_pointer = (Argv*)argv;
pthread_mutex_lock(&argv_pointer->type1->mutex_one);
printf("0x%lx wait type2",pthread_self());
sleep(1);
pthread_mutex_lock(&argv_pointer->type2->mutex_two);
pthread_mutex_unlock(&argv_pointer->type1->mutex_one);
pthread_mutex_unlock(&argv_pointer->type2->mutex_two);
return (void*)0;
}
void* two_th(void* argv){
Argv* argv_pointer = (Argv*)argv;
pthread_mutex_lock(&argv_pointer->type2->mutex_two);
printf("0x%lx wait type2",pthread_self());
sleep(1);
pthread_mutex_lock(&argv_pointer->type1->mutex_one);
pthread_mutex_unlock(&argv_pointer->type2->mutex_two);
pthread_mutex_unlock(&argv_pointer->type1->mutex_one);
return (void*)0;
}


int main(int argc,char* argv1[]){
pthread_t thread_one,thread_two;
int err;
ArgvType1 argvtype1;
ArgvType2 argvtype2;
argvtype1.res = 0;
argvtype2.res = 0;
pthread_mutex_init(&argvtype1.mutex_one,NULL);
pthread_mutex_init(&argvtype2.mutex_two,NULL);

Argv argv={&argvtype1,&argvtype2};
if((err = pthread_create(&thread_one,NULL,one_th,(void*)&argv))!=0){
printf("thread_one create error");
}

if((err = pthread_create(&thread_two,NULL,two_th,(void*)&argv))!=0){
printf("thread_two create error");
}

pthread_join(thread_one,NULL);
pthread_join(thread_two,NULL);
pthread_mutex_destroy(&argv.type1->mutex_one);
pthread_mutex_destroy(&argv.type2->mutex_two);


return 0;
}

上面采用的是两把锁进行相互嵌套的形式,这样形式务必会造成死锁.解决方案已经在上面给出了

线程与信号

在前一篇幅Linux线程浅析[线程的同步和互斥之线程信号量]中我们提到了信号量,而这个信号量其实就是信号的量集,即信号的增减运算.而并非是具体的信号类型.在这里提到的信号,则被视为具体的信号类型.类似于进程中 kill -l 后显示出来的具体信号类型.

在进程中的主线程中我们有信号的捕获和屏蔽,但是在进程对应的子线程中,我们能否对其信号进行捕获或者屏蔽呢??

线程中的信号特点:

 1:进程中的每个线程都有自己的信号屏蔽字和信号未决字
2:信号的处理方式是进程中所有线程共享的
3:进程中的信号是传递到单个线程的
4:定时器是进程的资源,进程中所有的线程共享相同的定时器
子线程中调用alarm函数产生的alarm信号会发送给主线程

线程信号中的相关函数(sleep和parse都是可以由信号中断其状态的)

 #include<signal.h>
int pthread_sigmask(int how,const sigset_t *restrict set,sigset_t *restrict oset);
功能:线程的信号屏蔽
返回:成功返回0,失败返回错误编号

如何屏蔽信号:调用方式如下

 sigset_t set;
sigemptyset(&set);
sigaddset(&set,SIGALRM);
pthread_sigmask(SIG_SETMASK,&set,NULL);

由于时间上的原因,线程信号屏蔽就不在这里进行演示了,有空在补全吧.(线程在处理相关共享信号的时候,需要格外注意其使用)

欢迎持续访问博客