黑马程序员技术交流社区

标题: 线程死锁的问题 [打印本页]

作者: wudongzhe    时间: 2013-5-1 23:20
标题: 线程死锁的问题
本帖最后由 吴东泽 于 2013-5-2 23:22 编辑

当在方法声明的时候用到了关键字synchronized  后再在方法体中用synchronized就会发生死锁的情况呢?死锁还有在哪些情况导致? 平时写线程的时候要都注意些那些方面呢?
作者: Jacky_Chen1990    时间: 2013-5-1 23:32
以下是以前的摘抄一些笔记,希望可以帮助到你。
操作系统中有若干进程并发执行,它们不断申请、使用、释放系统资源,虽然系统的进
程协调、通信机构会对它们进行控制,但也可能出现若干进程都相互等待对方释放资源才能
继续运行,否则就阻塞的情况。此时,若不借助外界因素,谁也不能释放资源,谁也不能解
除阻塞状态。根据这样的情况,操作系统中的死锁被定义为系统中两个或者多个进程无限期
地等待永远不会发生的条件,系统处于停滞状态,这就是死锁。
产生死锁的原因主要是:
(1) 因为系统资源不足。
(2) 进程运行推进的顺序不合适。
(3) 资源分配不当等。
如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则
就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。
产生死锁的四个必要条件:
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之
一不满足,就不会发生死锁。
死锁的解除与预防:
理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和
解除死锁。所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确
定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态
的情况下占用资源。因此,对资源的分配要给予合理的规划
作者: pthuakai    时间: 2013-5-2 08:18
死锁就是操作系统中,共同资源分配不当导致的。只要你避免这个,一般就没有问题。比如现在有3个线程,每个线程需要两个打印机。现在有三个打印机,每个线程都分了一个,但是还缺一个,却没有打印机了。因而就不能继续运行下去,从而导致死锁。只要避免这样就可以了
作者: 高正新    时间: 2013-5-2 10:15
首先要明白死锁的原因,我有一个苹果,你有一个苹果,我只想要你手里的苹果来达到2个苹果,你也只想要我手里的苹果来达到2个苹果,我们互不相让,一直僵持,就导致了死锁。
正确使用synchronized是为了保证线程的安全,避免发生死锁。
作者: 郑雪    时间: 2013-5-2 10:47
高正新 发表于 2013-5-2 10:15
首先要明白死锁的原因,我有一个苹果,你有一个苹果,我只想要你手里的苹果来达到2个苹果,你也只想要我手 ...

我也是这么理解的,这种理解很形象啊。
作者: 余雷    时间: 2013-5-2 11:18
本帖最后由 余雷 于 2013-5-2 11:22 编辑

通常出现的死锁都有哪些呢?
    (1)忘记释放锁
[void data_process()  
{  
    EnterCriticalSection();  
    if(/* error happens */)  
        return;  
    LeaveCriticalSection();  
}  

void data_process()
{
    EnterCriticalSection();
    if(/* error happens */)
        return;
    LeaveCriticalSection();

}    (2)单线程重复申请锁
void sub_func()  
{  
    EnterCriticalSection();  
    do_something();  
    LeaveCriticalSection();  
}  
  
void data_process()  
{  
    EnterCriticalSection();  
    sub_func();  
    LeaveCriticalSection();  
}  

void sub_func()
{
    EnterCriticalSection();
    do_something();
    LeaveCriticalSection();
}

void data_process()
{
    EnterCriticalSection();
    sub_func();
    LeaveCriticalSection();
}   

(3)双线程多锁申请
void data_process1()  
{  
    EnterCriticalSection(&cs1);  
    EnterCriticalSection(&cs2);  
    do_something1();  
    LeaveCriticalSection(&cs2);  
    LeaveCriticalSection(&cs1);  
}  
  
void data_process2()  
{  
    EnterCriticalSection(&cs2);  
    EnterCriticalSection(&cs1);  
    do_something2();  
    LeaveCriticalSection(&cs1);  
    LeaveCriticalSection(&cs2);  
}  

void data_process1()
{
    EnterCriticalSection(&cs1);
    EnterCriticalSection(&cs2);
    do_something1();
    LeaveCriticalSection(&cs2);
    LeaveCriticalSection(&cs1);
}

void data_process2()
{
    EnterCriticalSection(&cs2);
    EnterCriticalSection(&cs1);
    do_something2();
    LeaveCriticalSection(&cs1);
    LeaveCriticalSection(&cs2);
}   

(4)环形锁申请
/*
*             A   -  B
*             |      |
*             C   -  D
*/  

    假设有A、B、C、D四个人在一起吃饭,每个人左右各有一只筷子。所以,这其中要是有一个人想吃饭,他必须首先拿起左边的筷子,再拿起右边的筷子。现在,我们让所有的人同时开始吃饭。那么就很有可能出现这种情况。每个人都拿起了左边的筷子,或者每个人都拿起了右边的筷子,为了吃饭,他们现在都在等另外一只筷子。此时每个人都想吃饭,同时每个人都不想放弃自己已经得到的一那只筷子。所以,事实上大家都吃不了饭。






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2