如何防止TThreadList死锁
我在多线程中的多个类中使用TThreadList,发现很容易发生死锁,如果防止死锁?
[解决办法]
LockList后不要忘记UnlockList
不要嵌套LockList/UnlockList对(这个要小心,比如你的基类里每个方法都用了Lock对, 继承后Lock了又调用基类的方法,或者相互调用都有可以嵌套)
[解决办法]
嵌套可以,但是你的思路不要乱
私有的不会相互影响
[解决办法]
私有的不会相互影响
[解决办法]
防止死锁要考虑的问题很多
使用TCriticalSection要释放
[解决办法]
try
{
LockList
...
}
__finally
{
UnlockList
}
[解决办法]
TThreadList 其实就是 TList + 临界段
可以这样使用 :
TThreadList *hlstThread = new TThreadList();
TList *lst = NULL;
lst = hlstThread-> LockList(); // 在这里进入临界段
// 使用lst 操作完成后
hlstThread-> UnlockList(); // 在这里退出临界段
他们必须配对使用否则,就会发生死锁
[解决办法]
try
{
LockList
...
}
__finally
{
UnlockList
}
===============================
很奇怪,我看到有很多人都喜欢这种写法,但是我很反对,万一LockList失败,那么也会执行到UnlockList,则这个执行就不是必要的,如果是多次嵌套,则中间有一次,出现如此错误,就会导致不必要的解锁,而导致访问冲突,或者说达不到Lock的效果。这只是其中一种情况。
另一种是创建一个对象然后释放。
TStringList *StringList;
try
{
StringList=new TStringList();
}
__finally
{
StringList-> Free();
}
象这种,如果是在new TStringList的时候,由于内存不足等原因,则导致不成功,同样会执行finally,则会有什么情况?StringList是一个无效的指针,去执行Free,导致的将可能是内存访问违例,甚至会引发线程崩溃。
虽然很多人都有使用try ... finally的习惯,为的就是保证内存被释放或者锁定的资源出现异常也能被解锁,但是使用不当也会带来严重的问题,或者说这个问题本身是不必要的。相反,换成下面的结构:
TStringList *StringList=new TStringList();
try
{
}
__finally
{
StringList-> Free();
}
当在new的时候就出现异常,根本就不用担心会执行到try,更不用担心执行到__finally。而会直接跳到外层的异常处理结构当中。
去年的时候,接手公司一个旧的项目,当时某高人写的代码,首先是如楼上,并且允许创建的线程是无限的,于是用户配置线程数达1.5k(还有其它的服务程序在同一机器运行,所以实际创建的线程数量只到1.2k就上不去了),从而由于try(create)finally (free) 的结构,而导致异常。当时承载的用户量是3.5k。出了问题就让查,结果就是查不出个所以然来。接手之后,我是很偶然地发现了使用的是这种结构(由于代码特别长,并且是后期加入的try...finally,代码显得有些乱)。