如何在线程之间传递锁

本文关键字:之间 线程 | 更新日期: 2023-09-27 18:23:54

我想

Monitor.Enter(this.StaticLock);
try
{
    // Do something ...
    ThreadPool.QueueUserWorkItem(state =>
    {
        try
        {
             // Do something else...
        }
        finally
        {
            Monitor.Exit(this.StaticLock);
        }
    });
}
catch (Exception)
{
    Monitor.Exit(this.StaticLock);
    throw;
}

但它不起作用,因为它不能对当前线程中不是Monitor.Enter的对象执行Monitor.Exit。如何做到这一点?我应该使用线程间通信吗?

如何在线程之间传递锁

如何在线程之间传递锁?

您在初始线程上输入监视器,例如线程Alpha。任何试图进入监视器的其他线程都将被阻止,直到监视器可用。

如果您想将锁转移到另一个线程,比如线程Bravo,同时在Bravo完成后仍然能够恢复线程Alpha并拥有监视器的所有权,那么您可以在监视器上将Alpha置于等待状态。如果线程Bravo在监视器上被阻塞,则它会唤醒并进入监视器。完成后,脉冲监视器,这将放弃Bravo对监视器的所有权,并将所有权转移回Alpha,Alpha会醒来并继续运行监视器的所有权。

如果你完全不清楚这一点,那么(1)你一开始就不应该试图这样做;如果你弄错了,这是非常危险的,(2)你应该读一下:

http://www.codeproject.com/Articles/28785/Thread-synchronization-Wait-and-Pulse-demystified

Semaphore允许您将它们锁定在一个线程中,并在另一个线程解锁。

但是这种行为对我来说很可疑……你到底想实现什么?在实践中几乎不应该这样做。

static readonly Semaphore semaphore = new Semaphore(1, 1);
void Method1()
{
    semaphore.WaitOne();
    try
    {
        // Do something ...
        new Thread(() =>
        {
            try
            {
                // Do something else...
            }
            finally
            {
                semaphore.Release();
            }
        }).Start();
    }
    catch (Exception)
    {
        semaphore.Release();
        throw;
    }
}

您可以为此使用Mutex。它们就像锁,但有更多的特点。它们也更贵。

你肯定已经知道,你在这里处于危险的境地。在线程之间传递锁是危险的。。。

一种选择是使用WaitHandle

var waitHandle = new AutoResetEvent(initialState: false);
ThreadPool.QueueUserWorkItem(state =>
{
    lock(this.staticLock)
    {
        try
        {
            // Do something ...
        }
        finally
        {
            waitHandle.Set();
        }
        // Do something else...
    }
}
waitHandle.WaitOne();

如果Eric Lippert的答案适合我,我会实现:

lock(this.StaticLock)
{
    ThreadPool.QueueUserWorkItem(state =>
    {
        lock(this.StaticLock)
        {
             // Do something ...
             Monitor.Pulse(this.StaticLock);
             // Do something else...
        }
    });
    Monitor.Wait(this.StaticLock);
}

不幸的是,这个解决方案并不能阻止另一个线程锁定它。Monitor.Wait和排队线程锁定之间的StaticLock