问题:根据线程安全的相关知识,分析以下代码,当调用Fun3方法时i>10时是否会引起死锁?并说明理由。
public void Fun3(int i) {
lock (this) {
if (i > 10) {
i--;
Fun3(i);
}
}
}
网上答案是:不会发生死锁,(但有一点int是按值传递的,所以每次改变的都只是一个副本,因此不会出现死锁。但如果把int换做一个object,那么死锁会发生)
------------------------------------------------------------------------------------
不会发生死锁是对的,但和按值传递好像没有什么关系,即使是引用类型还是不会死锁。
关键在于同一个线程里可以循环多次lock一个对象,这种情况下一个线程是怎样也不会死锁的。
即使多个线程也无非是一个等待另一个执行完再执行,同样不会死锁。
但如果这样写:
public void Fun3(int i) {
lock (this) {
if (i > 10) {
i--;
Action<int> action = Fun3;
var r = action.BeginInvoke(i, p => { }, null);
action.EndInvoke(r);
}
}
}
这里用BeginInvoke在线程池里执行Fun3,并用EndInvoke等待其执行完成。也就是说lock(this)后又等待另一个线程执行lock(this),这样就造成了循环等待的条件,并发生死锁。
如有不同意见敬请指出,谢谢!
死锁的四个必要条件:
- 互斥:一个资源不能同时由多于两个进程使用
- 持有并等待:已持有资源的进程需要新资源
- 不能抢占:不能从正持有资源的进程里强占资源
- 循环等待:若干进程之间形成一种头尾相接的循环等待资源关系
- Mutual exclusion condition: a resource that cannot be used by more than one process at a time
- Hold and wait condition: processes already holding resources may request new resources
- No preemption condition: No resource can be forcibly removed from a process holding it, resources can be released only by the explicit action of the process
- Circular wait condition: two or more processes form a circular chain where each process waits for a resource that the next process in the chain holds
浙公网安备 33010602011771号