第9章 线程编程_死锁

Posted 浅墨浓香

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第9章 线程编程_死锁相关的知识,希望对你有一定的参考价值。

5.6 死锁

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

(2)解决方案:

  ①方案1:按相同的次序锁定相应的共享资源

  ②方案2:使用pthread_mutex_trylock(),它是pthread_mutex_lock()函数的非阻塞版。

【编程实验】死锁

//dead_lock.c

#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.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_fn(void* arg)
{
    Storage* s = (Storage*)arg;

    //先对ResourceA加锁
    pthread_mutex_lock(&s->ra->mutex);
    sleep(1);
    
    printf("0x%lx is waiting for ResourceB...\n", pthread_self());
    //再次ResourceB加锁
    pthread_mutex_lock(&s->rb->mutex);
    printf("ResourceA value is:%d\n", s->ra->value);
    printf("ResourceB value is:%d\n", s->rb->value);
    
    pthread_mutex_unlock(&s->rb->mutex);
    pthread_mutex_unlock(&s->ra->mutex);

    return (void*)0;
}

void* b_fn(void* arg)
{
   /*死锁
    Storage* s = (Storage*)arg;

    //先对ResourceB加锁
    pthread_mutex_lock(&s->rb->mutex);
    sleep(1);
    
    printf("0x%lx is waiting for ResourceA...\n", pthread_self());
    //再次ResourceA加锁
    pthread_mutex_lock(&s->ra->mutex);
    printf("ResourceA value is:%d\n", s->ra->value);
    printf("ResourceB value is:%d\n", s->rb->value);
    
    pthread_mutex_unlock(&s->ra->mutex);
    pthread_mutex_unlock(&s->rb->mutex);
    */

    //解决方案:与a线程一样,按相同的次序加锁
    Storage* s = (Storage*)arg;

    //先对ResourceA加锁
    pthread_mutex_lock(&s->ra->mutex);
    sleep(1);
    
    printf("0x%lx is waiting for ResourceB...\n", pthread_self());
    //再次ResourceB加锁
    pthread_mutex_lock(&s->rb->mutex);
    printf("ResourceA value is:%d\n", s->ra->value);
    printf("ResourceB value is:%d\n", s->rb->value);
    
    pthread_mutex_unlock(&s->rb->mutex);
    pthread_mutex_unlock(&s->ra->mutex);


    return (void*)0;
}

int main(void)
{
    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};

    int err = 0;
    pthread_t   thread_a, thread_b;
    if((err = pthread_create(&thread_a, NULL, a_fn, (void*)&s)) !=0){
        fprintf(stderr, "pthread_create:%s\n", strerror(errno));
        exit(1);
    }
    if((err = pthread_create(&thread_b, NULL, b_fn, (void*)&s)) !=0){
        fprintf(stderr, "pthread_create:%s\n", strerror(errno));
        exit(1);
    }

    pthread_join(thread_a, NULL);
    pthread_join(thread_b, NULL);

    pthread_mutex_destroy(&ra.mutex);
    pthread_mutex_destroy(&rb.mutex);

    return 0;
}
/*
 0xb6d08b70 is waiting for ResourceB...
 ResourceA value is:100
 ResourceB value is:200    //死锁时,停在这个位置
 0xb7709b70 is waiting for ResourceB...
 ResourceA value is:100
 ResourceB value is:200    //未发生死锁时会输出到这里
 */

以上是关于第9章 线程编程_死锁的主要内容,如果未能解决你的问题,请参考以下文章

第9章 线程编程_线程同步1:互斥锁

第1章 并发编程的挑战

[Linux用户空间编程-7]:pThread线程库-线程管理代码示例

day10-python并发编程之多线程协程及MySQL

第13章 TCP编程_基于自定义协议的多线程模型

Java并发编程实战 04死锁了怎么办?