首页 > 代码库 > 第9章 线程编程(8)_死锁

第9章 线程编程(8)_死锁

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章 线程编程(8)_死锁