Linux多线程10-死锁

有时,一个线程需要同时访问两个或更多不同的共享资源,而每个资源又都由不同的互斥量管理。当超过一个线程加锁同一组互斥量时,就有可能发生死锁。

两个或两个以上的进程在执行过程中,因争夺共享资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁。

死锁的几种场景:

  • 忘记释放锁
  • 重复加锁
  • 多线程多锁,抢占锁资源

image

代码示例:

  1. 重复加锁或忘记解锁的情况

    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    
    int tickets = 1000; //所有线程都共享这100张票
    
    //创建一个互斥量
    pthread_mutex_t mutex;
        
    void* sellticket(void* arg){
    
        while(1){
            //加锁
            pthread_mutex_lock(&mutex);
            //重复加锁
            //pthread_mutex_lock(&mutex); //程序卡住 无法执行
            
            if(tickets > 0){
                // 卖票
                // 我们要求在A线程操作共享数据时, B,C线程不允许操作
                usleep(6000); 
                printf("%ld 正在卖第 %d 张门票\n", pthread_self(), tickets);
                tickets--;
            }else{
                pthread_mutex_unlock(&mutex);
                break;
            }
            //解锁
            pthread_mutex_unlock(&mutex); //忘记解锁会程序阻塞产生死锁
        }
    
        return NULL;
    }
    
    int main(){
        //初始化互斥量
        pthread_mutex_init(&mutex, NULL);
        //创建3个子线程
        pthread_t tid1, tid2, tid3;
        pthread_create(&tid1, NULL, sellticket, NULL);
        pthread_create(&tid2, NULL, sellticket, NULL);
        pthread_create(&tid3, NULL, sellticket, NULL);
    
        //回收子线程资源, 阻塞
        pthread_join(tid1, NULL);
        pthread_join(tid2, NULL);
        pthread_join(tid3, NULL);
    
        pthread_exit(NULL);  //退出主线程
    
        //释放互斥量资源
        pthread_mutex_destroy(&mutex);
        return 0;
    }
    
  2. 多线程多锁, 抢占锁资源

    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    
    //创建两个互斥量
    pthread_mutex_t mutex1, mutex2;
    
    void* workA(void* arg){
        pthread_mutex_lock(&mutex1);
        sleep(1);
        pthread_mutex_lock(&mutex2);
    
        printf("workA...\n");
    
        pthread_mutex_unlock(&mutex2);
        pthread_mutex_unlock(&mutex1);
        return NULL;
    }
    
    void* workB(void* arg){
        pthread_mutex_lock(&mutex2);
        sleep(1);
        pthread_mutex_lock(&mutex1);
    
        printf("workB...\n");
    
        pthread_mutex_unlock(&mutex1);
        pthread_mutex_unlock(&mutex2);
        return NULL;
    }
    
    int main(){
        //初始化互斥量
        pthread_mutex_init(&mutex1, NULL);
        pthread_mutex_init(&mutex2, NULL);
    
        //创建2个子线程
        pthread_t tid1, tid2;
        pthread_create(&tid1, NULL, workA, NULL);
        pthread_create(&tid2, NULL, workB, NULL);
    
        //回收子线程资源
        pthread_join(tid1, NULL);
        pthread_join(tid2, NULL);
        
        //释放互斥量资源
        pthread_mutex_destroy(&mutex1);
        pthread_mutex_destroy(&mutex2);
        return 0;
    }
    
posted @ 2023-06-26 08:58  言叶以上  阅读(65)  评论(0编辑  收藏  举报