Linux学习_线程的死锁和信号
Posted Leslie X徐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux学习_线程的死锁和信号相关的知识,希望对你有一定的参考价值。
线程的死锁,信号的概念
死锁
- 概念
- 死锁:
- 两个线程试图同时占用两个资源,并按不同的次序锁定相应的共享资源。
- 解决方式:
- 按相同的次序锁定相应的共享程序。
- 使用函数pthread_mutex_trylock(),它是函数函数pthread_mutex_lock()的非阻塞函数。
- 示例:
/*
* dead_lock.c
*
*
*/
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//两个共享资源
typedef struct
{
int value;
pthread_mutex_t mutex;
}ResourceA;
typedef struct
{
int value;
pthread_mutex_t mutex;
}ResourceB;
typedef struct
{
ResourceA *ra;
ResourceB *rb;
}Storage;
void* a_fun(void* arg)
{
Storage *s = (Storage*)arg;
//对ResouceA加锁
pthread_mutex_lock(&s->ra->mutex);
printf("0x%lx is waiting for ResouceB...\\n",pthread_self());
sleep(1);
//对ResouceB加锁
pthread_mutex_lock(&s->rb->mutex);
++s->rb->value;
printf("ResouceA value is:%d\\n",s->ra->value);
printf("ResouceB value is:%d\\n",s->rb->value);
pthread_mutex_unlock(&s->ra->mutex);
pthread_mutex_unlock(&s->rb->mutex);
return (void*)0;
}
void* b_fun(void* arg)
{
Storage *s = (Storage*)arg;
//-------------------------死锁程序-----------------------------
//对ResouceB加锁
//pthread_mutex_lock(&s->rb->mutex);
//sleep(1);
//printf("0x%lx is waiting for ResouceA...\\n",pthread_self());
对ResouceA加锁
//pthread_mutex_lock(&s->ra->mutex);
//printf("ResouceA value is:%d\\n",s->ra->value);
//printf("ResouceB value is:%d\\n",s->rb->value);
//pthread_mutex_unlock(&s->ra->mutex);
//pthread_mutex_unlock(&s->rb->mutex);
//--------------------------正常程序------------------------------
//对ResouceA加锁
pthread_mutex_lock(&s->ra->mutex);
printf("0x%lx is waiting for ResouceA...\\n",pthread_self());
sleep(1);
//对ResouceB加锁
pthread_mutex_lock(&s->rb->mutex);
++s->ra->value;
printf("ResouceA value is:%d\\n",s->ra->value);
printf("ResouceB value is:%d\\n",s->rb->value);
pthread_mutex_unlock(&s->ra->mutex);
pthread_mutex_unlock(&s->rb->mutex);
return (void*)0;
}
int main(int argc, char **argv)
{
ResourceA ra;
ResourceB rb;
ra.value = 100;
rb.value = 200;
pthread_mutex_init(&ra.mutex, NULL);
pthread_mutex_init(&rb.mutex, NULL);
Storage s={&ra, &rb};
printf("ResouceA value is:%d\\n",ra.value);
printf("ResouceB value is:%d\\n",rb.value);
int err;
pthread_t thread_a, thread_b;
err = pthread_create(&thread_a, NULL, a_fun, (void*)&s);
if(err)
{fprintf(stderr, "pthread_create:%s\\n",strerror(0));exit(1);}
err = pthread_create(&thread_b, NULL, b_fun, (void*)&s);
if(err)
{fprintf(stderr, "pthread_create:%s\\n",strerror(0));exit(1);}
pthread_join(thread_a,NULL);
pthread_join(thread_b,NULL);
pthread_mutex_destroy(&ra.mutex);
pthread_mutex_destroy(&rb.mutex);
return 0;
}
输出:
ResouceA value is:100
ResouceB value is:200
0xb6ddf460 is waiting for ResouceB...
ResouceA value is:100
ResouceB value is:201
0xb65de460 is waiting for ResouceA...
ResouceA value is:101
ResouceB value is:201
线程和信号
- 概念
- 进程中每个线程都有自己的信号屏蔽字和信号未决字
- 信号的处理方式是进程中所有线程共享的
- 进程中的信号是递送到单个线程的
- 定时器是进程资源,进程中所有的线程共享相同的定时器
- 子线程调用alarm()函数产生的alarm信号发送给主控线程。
- 函数原型
#include <signal.h>
int pthread_sigmask(
int how,
const sigset_t* restrict set,
sigset_t* restrict oset);
- 功能:线程的信号屏蔽
- 返回:成功返回0,出错返回错误编号
- 案例
/*
* pthread_alarm.c
*
* 主线程睡眠10秒,子线程2秒输出一个信号
*/
#include <pthread.h>
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void sig_handle(int signo)
{
printf("pthread id in the sig_handler: %lx\\n",pthread_self());
if(signo==SIGALRM) printf("timeout...\\n");
alarm(2);
}
void* th_fn(void* arg)
{
if(signal(SIGALRM, sig_handle)==SIG_ERR) perror("error");
//在子线程中设置定时器,若不设置则无法接收信号
alarm(2);
int i;
for(i=1;i<=100;++i){
printf("(%lx) i: %d\\n",pthread_self(),i);
sleep(1);
}
return (void*)0;
}
int main(int argc, char **argv)
{
pthread_t th;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
int err=pthread_create(&th, &attr, th_fn, (void*)0);
if(err)perror("error");
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGALRM);
//对主控线程屏蔽SIGALRM信号
pthread_sigmask(SIG_SETMASK, &set, NULL);
while(1){
printf("control thread(%lx) is running...\\n",pthread_self());
sleep(10);
//睡眠中主控信号接收到信号会中断睡眠继续运行
}
printf("control thread over\\n");
return 0;
}
输出:
control thread(b6fa70c0) is running...
(b6dd3460) i: 1
(b6dd3460) i: 2
pthread id in the sig_handler: b6dd3460
timeout...
(b6dd3460) i: 3
(b6dd3460) i: 4
pthread id in the sig_handler: b6dd3460
timeout...
(b6dd3460) i: 5
(b6dd3460) i: 6
pthread id in the sig_handler: b6dd3460
timeout...
(b6dd3460) i: 7
(b6dd3460) i: 8
pthread id in the sig_handler: b6dd3460
timeout...
(b6dd3460) i: 9
(b6dd3460) i: 10
control thread(b6fa70c0) is running...
pthread id in the sig_handler: b6dd3460
timeout...
(b6dd3460) i: 11
(b6dd3460) i: 12
pthread id in the sig_handler: b6dd3460
timeout...
(b6dd3460) i: 13
^C
以上是关于Linux学习_线程的死锁和信号的主要内容,如果未能解决你的问题,请参考以下文章