首页 > 系统相关 >Linux多线程10-死锁

Linux多线程10-死锁

时间:2023-06-26 09:14:07浏览次数:38  
标签:10 NULL 互斥 死锁 mutex pthread 线程 多线程

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

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

死锁的几种场景:

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

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;
    }
    

标签:10,NULL,互斥,死锁,mutex,pthread,线程,多线程
From: https://www.cnblogs.com/anqwjoe/p/17504452.html

相关文章

  • Linux多线程12-生产者和消费者模型
    一个最简单的生产者消费者模型/*生产者消费者模型(粗略版)*/#include<stdio.h>#include<pthread.h>#include<stdlib.h>#include<unistd.h>structNode{intnum;structNode*next;};//头节点structNode*head=NULL;void*producer(void*arg){......
  • Linux多线程11-读写锁
    当有一个线程已经持有互斥锁时,互斥锁将所有试图进入临界区的线程都阻塞住。但是考虑一种情形,当前持有互斥锁的线程只是要读访问共享资源,而同时有其它几个线程也想读取这个共享资源,但是由于互斥锁的排它性,所有其它线程都无法获取锁,也就无法读访问共享资源了,但是实际上多个线程同时......
  • Linux多线程14-信号量
    信号量的类型sem_tintsem_init(sem_t*sem,intpshared,unsignedintvalue);初始化信号量参数:-sem:信号量变量地址-pshared:0用在线程间,非0用在进程间-value:信号量中的值intsem_destroy(sem_t*sem);释放资......
  • Linux多线程13-条件变量
    上节代码存在的问题:生产者已经没有数据了,消费者还在while循环判断是否有数据,浪费资源没有数据了应该通知生产者生产,生产好了通知消费者消费这就需要条件变量pthread_cond_tintpthread_cond_init(pthread_cond_t*restrictcond,constpthread_con......
  • Linux多线程01-线程概述
    线程概述与进程(process)类似,线程(thread)是允许应用程序并发执行多个任务的一种机制。一个进程可以包含多个线程。同一个程序中的所有线程均会独立执行相同程序,且共享同一份全局内存区域,其中包括初始化数据段、未初始化数据段,以及堆内存段。(传统意义上的UNIX进程只是多线程程序......
  • Linux多线程02-创建线程
    pthread_create描述:pthread_create()函数在调用进程中创建一个新的线程。新线程通过调用start_routine()开始执行,arg作为start_routine()的唯一参数传递。新线程以以下方式之一终止:调用pthread_exit(3),指定可供调用同一进程中pthread_join(3)的其他线程使用的退......
  • Linux多线程04-连接已终止的线程
    pthread_join描述:pthread_join()函数等待由thread指定的线程终止。如果该线程已经终止,则pthread_join()将立即返回。由thread指定的线程必须是可连接的。如果retval不为NULL,则pthread_join()将目标线程的退出状态(即目标线程提供给pthread_exit(3)的值)复制到retval指向的......
  • Linux多线程03-终止线程
    pthread_exit和pthread_self和pthread_equal描述:pthread_exitpthread_exit()函数终止调用该函数的线程,并通过retval返回一个值,如果该线程是可连接的,则在同一进程中调用pthread_join(3)的另一个线程可以获取该值。任何由pthread_cleanup_push(3)建立但尚未弹出的清理处......
  • Linux多线程07-线程属性
    线程属性类型:pthread_attr_t描述:pthread_attr_setdetachstate()函数将由attr引用的线程属性对象的分离状态属性设置为detachstate中指定的值。分离状态属性确定使用线程属性对象attr创建的线程将在可连接状态还是分离状态下创建。可以在detachstate中指定以下值:P......
  • Linux多线程06-线程取消
    pthread_cancel描述:pthread_cancel()函数向线程thread发送一个取消请求。目标线程对取消请求的响应取决于该线程控制的两个属性:其取消状态和类型。一个线程的取消状态由pthread_setcancelstate(3)确定,可以启用(对于新线程而言是默认的)或禁用。如果一个线程已禁用取消,则取消请......