0

抱歉标题,我找不到更好的解释我的问题...

我很难在我的应用程序中同步不同的线程。对于对这个问题有新看法的人来说,这可能是一个简单的问题,但是经过数小时对死锁的调查,我的脑袋快要爆炸了,我找不到一个好的和安全的方法来编写我的同步机制:(

基本上,我有一个在多个线程中运行的 .Net 进程(一切都在一个进程中,因此不需要 IPC)。我有 4 个线程:

  • 1个线程,说它叫做SpecificThread。有一个System.Timers.Timer定期执行一些代码。
  • 3 个其他线程,每个线程都运行一个定期执行某些代码的服务(while (true)循环 + Thread.Sleep(few ms))。

所有 3 项服务必须同时运行。我保证它们的并发执行是线程安全的。第四个线程SpecificThread必须定期执行其代码,但它必须阻止其他 3 个服务的执行

所以基本上我有SpecificThread定期执行代码。当SpecificThread想要定期执行其代码时,它必须等待其他服务完成它们的任务。当所有其他 3 个服务完成他们的任务时,它必须执行其SpecificCode而其他 3 个服务被阻止。当其SpecificCode被执行时,其他3个服务可以再次运行它们的代码。

我有一个SynchronizationContext在所有 4 个线程之间共享的对象的共享实例。我可以用它来同步我的线程:

public class SynchronizationContext
{
    public void StartService1()
    {
        ...
    }   
    public void StopService1()
    {
        ...
    }
    ...

    public void StartSpecificCode()
    {
        // Some sync here that wait until all 3 services completed their
        // respective tasks
    }
    public void NotifySpecificCodeCompleted()
    {
        // Some sync here that allows services 1 to 3 to execute again
    }
}

3个服务执行机制如下:

// Only exits the loop when stopping the whole .Net process
while (myService.IsRunning)
{
    try
    {
        this.synchronizationContext.StartService1();

        // Do some job
    }
    finally
    {
        this.synchronizationContext.EndService1();

        // Avoids too much CPU usage for nothing in the loop
        Thread.Sleep(50);
    }
}

具体线程执行机制:

// System.Timers.Timer that is instantiated on process start
if (this.timer != null)
{
    this.timer.Stop();
}

try
{
    // Must blocks until computation is possible
    this.synchronizationContext.StartSpecificCode();

    // Some job here that must execute while other 3
    // services are waiting
}
finally
{
    // Notify computation is done
    this.synchronizationContext.NotifySpecificCodeCompleted();

    // Starts timer again
    if (this.timer != null)
    {
        this.timer.Start();
    }
}

我不知道如何使用关键部分,因为只有SpecificThread在其他部分等待时才必须运行。我没有找到一种方法,Semaphore也没有AutoResetEvent(它们的使用在我的代码中引入了难以调试的死锁)。我的想法已经用完了......也许Interlocked静态方法会有所帮助?

最后一句话:我的代码必须使用 .Net 3.5 运行,我不能使用任何 TPL 或CountdownEvent类...

任何帮助表示赞赏!

4

1 回答 1

1

ReaderWriterLockSlim听起来正是最能帮助您的工具。让每个服务在其循环体内取出一个读锁:

while (true)
{
    try
    {
        lockObject.EnterReadLock();

        //Do stuff
    }
    finally
    {
        lockObject.ExitReadLock();
    }
}

然后你的第四个线程可以在它想要完成它的工作时进入一个写锁。读取器/写入器锁的工作方式是任意数量的读取器都可以持有锁,只要没有写入器持有锁,并且一次只能有一个写入器持有锁。这意味着三个工作人员都不会阻塞其他工作人员,但如果第四个线程正在运行,工作人员将阻塞,这正是您想要的。

于 2013-03-28T13:17:42.967 回答