一起talk C栗子吧(第一百一十七回:C语言实例--线程死锁一)



各位看官们,大家好,上一回中咱们说的是线程同步之互斥量的例子,这一回咱们说的例子是:线程死锁。闲话休提,言归正转。让我们一起talk C栗子吧!

我们在前面章回中介绍互斥量相关的函数时提到过死锁,不过当时没有做详细的介绍,有些看官对死锁不明白。因此,我们在今天的章回中详细介绍死锁,并且使用线程来显示死锁。

死锁就是不同的程序在运行时因为某种原因发生了阻塞,进而导致程序不能正常运行。阻塞程序的原因通常都是由于程序没有正确使用临界资源。

我们举个日常生活中的例子来比喻死锁。我们把马路上行驶的汽车比作运行着的程序,把马路比作临界资源,如果有两辆汽车相互碰撞,就会把车停在马路上,这样的话他们一直占用着马路这个临界资源。其它的汽车不能正常通过马路,于是整条路上的汽车都无法在马路上正常行驶,马路也被汽车堵的水泄不通。整个交通都瘫痪了,这就是“死锁”。造成死锁的原因就是发生车祸的汽车占用了马路这种临界资源,以至于其它汽车无法在马路上正常行驶。

在实际的程序中造成死锁的原因有两种

  1. 同一个线程对已经加锁的互斥量再次加锁;
  2. 线程A对互斥量一加锁,同时等待互斥量二被解锁;而此时,线程B对互斥量二加锁,同时等待互斥量一被解锁;

第一种原因相对来说容易避免,毕竟在同一个线程中,避免两次加锁操作还是容易做到的。此外,我们还可以使用尝试性加锁函数:pthread_mutex_trylock对互斥量加锁。

我们写一个伪代码来演示死锁

thread_func() //线程执行函数
{

    lock(mutex_value);  //第一次对互斥量进行加锁
    //do some thing
    lock(mutex_value);  //第二次对互斥量进行加锁,死锁发生
    // do another thing
    unlock(mutex_value); //对互斥量进行解锁操作
    unlock(mutex_value);
}

第二种原因就不容易发现了,线程A锁着互斥量一不放,同时等待互斥量二被解锁;而线程B锁着互斥量二不放,同时等待互斥量一被解锁。它们都在等待互斥量被解锁,但是却不肯对被自己加锁的互斥量进行解锁操作,因此就发生了死锁。这种死锁是在两个线程中操作不同的互斥量造成的,因此不容易被发现。这就需要我们不断地积累经验来避免死锁发生。

我们写一个伪代码来演示死锁

thread_funcA() //线程A的执行函数
{

    lock(mutex_value1);  //对互斥量一进行加锁
    //do some thing
    lock(mutex_value2);  //对互斥量二进行加锁,等待互斥量二被解锁
    // do another thing
    unlock(mutex_value2); //对互斥量二进行解锁操作
    unlock(mutex_value1); //对互斥量一进行解锁操作
}
thread_funcB() //线程B的执行函数
{

    lock(mutex_value2);  //对互斥量二进行加锁
    //do some thing
    lock(mutex_value1);  //对互斥量一进行加锁,等待互斥量一被解锁
    // do another thing
    unlock(mutex_value1); //对互斥量一进行解锁操作
    unlock(mutex_value2); //对互斥量二进行解锁操作
}

程序发生死锁后就会一直阻塞,直到消耗完系统资源为止。因此,我们一定要正确使用互斥量以及线程,不然会在程序中造成严重的错误。

各位看官,关于死锁的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解 。


时间: 2025-01-13 10:39:05

一起talk C栗子吧(第一百一十七回:C语言实例--线程死锁一)的相关文章

一起talk C栗子吧(第一百一十九回:C语言实例--线程死锁三)

各位看官们.大家好,上一回中咱们说的是线程死锁的样例,这一回咱们继续说该样例.闲话休提,言归正转.让我们一起talk C栗子吧! 看官们,由于篇幅的原因我们在上一回仅仅介绍了死锁发生的第一种原因,今天我们将介绍死锁发生的另外一种原因,而且该原因中的伪代码转换为实际的C语言代码. 为了方便,我们使用前面章回中演示相互排斥量的代码,在该代码的基础上做一些小改动来演示死锁.代码例如以下: 首先定义两个相互排斥量,相互排斥量是全局变量.方便线程使用. #if MUTEX_ENABLE pthread_m

一起talk C栗子吧(第一百二十一回:C语言实例--线程知识体系图)

各位看官们,大家好,上一回中咱们说的线程属性的例子,这一回咱们说的例子是:线程知识体系图.闲话休提,言归正转.让我们一起talk C栗子吧! 我们在前面的章回中介绍了与线程相关的知识,在今天的章回中,我们将对这些知识进行总结,并且整理成一张知识体系图,方便大家掌握线程相关的知识. 下面是我们整理的知识体系图,请大家参数: 上图内容中的知识点都有相应的章回对应,下面是我整理的章回对应关系.为了大家方便,我设置了链接,大家可以直接点击链接跳到相应的章回中. 线程概念 线程概念:第一百零七回 线程标识

一起talk C栗子吧(第十七回:C语言实例--栈二)

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例.闲话休提, 言归正转.让我们一起talk C栗子吧! 看官们,上一回中咱们说的是栈和特点和基本操作,最后通过顺序存储的方式实现了栈,这一回咱们继续 说栈,不过咱们这一回说的是栈的链式存储方式. 在代码中通过双向链表来实现栈的链式存储.入栈操作沿着表头到表尾的方向进行,出栈操作与其正好相 反(就把它当作双向链表的一个使用实例吧).栈的结点可以看作是链表中的结点,对栈的操作,可以看 作是在链表中进行插入或者删除结点

一起talk C栗子吧(第二回:C语言实例--判断闰年)

各位看官们,大家好,从今天开始,我们讲大型章回体科技小说 :C栗子,也就是C语言实例.闲话休提, 言归正转.让我们一起talk C语言实例吧! 看官们,上一回中咱们给小说做了个开头,这一回咱们正式说C例子,这回说的例子是:判断闰年. 看官们,闰年是什么?这个是地理天文方面的概念.如果不明白的话,自己百度去,哈哈.我也偷一把懒. 看官们,判断闰年的方法有两种: 如果某年能被4整除,但是不能被100整除,那么这一年就是闰年. 如果某年能被400整除,那么这一年就是闰年. 看官们看到整除肯定想到除法了

一起talk C栗子吧(第一百一十六回:C语言实例--线程同步之互斥量二)

各位看官们,大家好,上一回中咱们说的是线程同步之信号量的例子,这一回咱们继续说该例子.闲话休提,言归正转.让我们一起talk C栗子吧! 我们在上一回中详细介绍了互斥量相关函数的用法,这一回中,我们介绍如何使用这些函数来操作互斥量. 下面是详细的操作步骤: 1.定义一个互斥量A,用来同步线程: 2.在创建线程的进程中使用pthread_mutex_init函数初始化互斥量,互斥量的属性使用默认值: 3.在读取数据的线程中读取数据,首先使用pthread_mutex_lock函数对互斥量A进行加锁

一起talk C栗子吧(第一百一十二回:C语言实例--线程同步概述)

各位看官们,大家好.上一回中咱们说的是线程间通信的样例,这一回咱们说的样例是:线程同步.闲话休提,言归正转.让我们一起talk C栗子吧! 看官们,提到同步.我想大家都不陌生,由于我们在前面章回中介绍过进程同步的内容. 大家都知道线程是轻量级的进程,尽管线程不像进程一样须要专门的通信机制,可是线程须要专门的同步机制. 今天我们来介绍一下线程同步的内容. 同步的含义对于进程和线程是同样的.仅仅是进程和线程实现同步的方式不同样.关于同步的含义,我们就不做具体的介绍了,假设大家忘记了,能够点击这里查看

一起talk C栗子吧(第一百四十七回:C语言实例--socket通信一)

各位看官们,大家好,上一回中咱们说的是socket属性的例子,这一回咱们说的例子是socket通信.闲话休提,言归正转.让我们一起talk C栗子吧! 看官们,我们在前面章回中介绍了socket的基本概述,这一回中我们将介绍如何使用socket来实现两个进程之间的通信.为了方便大家理解socket通信的方式,我们把通信的双方分别称作客户端和服务器端.大家都知道,套接字有两种类型:流套接字和数据报套接字.不同类型的套接字,通信的方式也不同,本章回中我们先介绍流套接字的通信方式,数据报套接字的通信方

第一百一十七天 how can I 坚持

今天其实是很烦躁的一天.浑身乏力,好蛋疼,很多事,都感觉很压抑,效率很低. 过滤器: web.xml配置: <filter> <filter-name>mobileFilter</filter-name> <filter-class>com.oauth.system.utils.MobileFilter</filter-class> <init-param> <param-name>logonStrings</par

python第一百一十七天-----ModelForm组件

Model + Form => 验证 + 数据库操作 - class LoginModelForm(xxxxx): 利用model.A中的字段 1. 生成HTML标签:class Meta: ... 2. mf = xxxModelForm(instance=ModelObj) 3. 额外的标签, is_rmb = Ffields.CharField(widget=Fwidgets.CheckboxInput()) 4. 各种验证 is_valid() -> 各种钩子... 5. mf.sav