码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2016-02-02 15:15:56      阅读:123      评论:0      收藏:0      [点我收藏+]

标签:


各位看官们,大家好,上一回中咱们说的是线程同步之互斥量的例子,这一回咱们说的例子是:线程死锁。闲话休提,言归正转。让我们一起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); //对互斥量二进行解锁操作
}

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

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


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

标签:

原文地址:http://blog.csdn.net/talk_8/article/details/50620580

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!