在服务器应用程序中,我们有以下内容: 一个称为JobManager的类,它是一个单例。 另一个类Scheduler会不断检查是否需要将任何作业添加到JobManager。死锁Delphi解释/解决方案
当是时候这样做,调度这样做:
TJobManager.Singleton.NewJobItem(parameterlist goes here...);
同时,客户端应用程序,用户做一些事情,产生对服务器的调用。在内部,服务器向自己发送消息,并且侦听该消息的其中一个类是JobManager。 的JobManager处理消息,并知道它是一次新的工作添加到列表中,调用自身的方法:
NewJobItem(parameter list...);
在NewJobItem方法,我有这样的事情:
CS.Acquire;
try
DoSomething;
CallAMethodWithAnotherCriticalSessionInternally;
finally
CS.Release;
end;
这种情况发生时系统达到死锁(CS.Acquire)。 客户端和服务器应用程序之间的通信是通过Indy 10进行的。 我认为,启动发送消息给JobManager的服务器应用程序方法的RPC调用正在Indy线程的上下文中运行。
调度程序有其自己的线程正在运行,并直接调用JobManager方法。这种情况容易发生死锁吗? 有人能帮我理解为什么这里发生了一个僵局吗?我们知道,有时,当客户端做了一个特定的动作,导致系统锁定,那么我终于可以找到这一点,同一班级的关键部分从不同的点到达两次调度程序和JobManager的消息处理程序方法)。
一些更多的信息
我想补充一点,(这可能是愚蠢的,但无论如何...)的DoSomething的里面还有另外一个
CS.Acquire;
try
Do other stuff...
finally
CS.Release;
end;
这种内部CS.Release做什么都是外在的CS.Acquire?如果是这样,这可能是调度程序进入关键部分的地步,并且所有的锁定和解锁都变得一团糟。
关键部分的目的是为了保护不能在不同线程上同时执行的代码,所以如果在同一个实例上的关键部分达到两次(或更多)是好的,因为这意味着关键部分是在那里工作,它是为此而设计的!坏消息是当CS1因为获取线程正在等待获取CS2而没有释放,而CS2由于获取线程正在等待获取CS1(称为DeadLock)而未释放。从你说的话,我不确定你正在经历一个僵局......你为什么确定? – jachguate 2011-05-11 02:30:54
调试时,按照消息处理程序方法,我刚刚进入临界区,并且CS.Acquire行处的断点再次到达调度程序 - 再次触发F8,系统停止。 – ronaldosantana 2011-05-11 03:01:02
您也可以在Windows消息处理循环中发生死锁。当ThreadA在CS1上有一个锁定,然后进行需要消息循环循环的调用时;并且线程B实际上在等待获取CS1时停止,中断或无限期地延迟消息循环... – 2011-05-11 06:11:30