【多线程编程学习笔记12】如何避免线程发生死锁?_如何在多线程中避免发生死(2)

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

[root@localhost ~]# gcc thread.c -o thread.exe -lpthread
[root@localhost ~]# ./thread.exe
线程 3135751936 创建完成
线程 3125262080 创建完成
线程 3114772224 创建完成
线程 3135751936 已加锁
线程 3104282368 创建完成
线程 3135751936 执行完成
<-- 其它 3 个线程发生了死锁

程序中共创建了 4 个线程,它们都执行 thread_func() 函数,该函数内完成了对互斥锁的“加锁”操作,但没有调用 pthread_mutex_unlock() 函数对互斥锁“解锁”。通过程序的执行结果可以看到,4 个线程中仅有 1 个线程成功执行结束,其它 3 个线程一直处于等待互斥锁“解锁”的阻塞状态,发生了死锁。

再举一个例子(实例二):

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t mutex;
pthread_mutex_t mutex2;
void *func1(void *args)
{
    pthread_mutex_lock(&mutex);
    printf("t1 成功申请 mytex 锁\n");
    sleep(2);
    pthread_mutex_lock(&mutex2);
    printf("t1 成功申请 mytex2 锁\n");
    printf("%u is running\n",pthread_self());
    pthread_mutex_unlock(&mutex);
    printf("------%u done\n",pthread_self());      
}
void *func2(void *args)
{ 
    pthread_mutex_lock(&mutex2);
    printf("t2 成功申请 mytex2 锁\n");
    sleep(2);
    pthread_mutex_lock(&mutex);
    printf("t2 成功申请 mytex 锁\n");
    printf("%u is running\n",pthread_self()); 
    pthread_mutex_unlock(&mutex);
    printf("------%u done\n",pthread_self());
}
int main()
{
    int ret;
    pthread_t t1;
    pthread_t t2;
    pthread_mutex_init(&mutex,NULL);
    pthread_mutex_init(&mutex2,NULL);
    ret = pthread_create(&t1, NULL, func1, NULL);
    if(ret != 0){
           printf("create t1 fail\n");
    }
    ret = pthread_create(&t2, NULL, func2, NULL);
    if(ret != 0){
           printf("create t2 fail\n");
    }
  
    pthread_join(t1,NULL);
    pthread_join(t2,NULL);
    pthread_mutex_destroy(&mutex);
    pthread_mutex_destroy(&mutex2);
    return 0;
}

假设程序编写在 thread.c 文件中,执行过程如下:

[root@localhost ~]# gcc thread.c -o thread.exe -lpthread
[root@localhost ~]# ./thread.exe
t1 成功申请 mytex 锁
t2 成功申请 mytex2 锁
<-- t1 和 t2 都发生了死锁

程序中创建了 mutex 和 mutex2 两个互斥锁,线程 t1 和 t2 同时执行。从执行结果可以看到,t1 成功申请了 mutex 锁,t2 成功申请了 mutex2 锁,t1 一直等待 t2 释放 mutex2 锁,而 t2 一直等待 t1 释放 mutex 锁,两个线程都因等待对方释放资源产生了死锁。

总的来说,当进程空间中的某公共资源不允许多个线程同时访问时,某线程访问公共资源后不及时释放资源,就很可能产生线程死锁。

避免线程死锁的几点建议

  1. 使用互斥锁、信号量、条件变量和读写锁实现线程同步时,要注意以下几点:
  • 占用互斥锁的线程,执行完成前必须及时解锁;
  • 通过 sem_wait() 函数占用信号量资源的线程,执行完成前必须调用 sem_post() 函数及时释放;
  • 当线程因 pthread_cond_wait() 函数被阻塞时,一定要保证有其它线程唤醒此线程;
  • 无论线程占用的是读锁还是写锁,都必须及时解锁。

注意,函数中可以设置多种结束执行的路径,但无论线程选择哪个路径结束执行,都要保证能够将占用的资源释放掉。

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

et/topics/618658159)**

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值