-1

假设有一个函数在任何给定时间只能由一个线程执行,其余的只是返回(因为已经在处理特定状态),实现这一点的最佳方法是什么?

public void RunOnce()
{
    if(Interlocked.Exchange(ref m_isRunning, 1) == 1)
        return;

    // Run code that should only be executed once
    
    // What mechanism do we use here to ensure thread safety?
    Volatile.Write(ref m_isRunning, 0);
}

如果 m_isRunning 是一个状态(即表示枚举的整数),是否会应用相同的机制?

4

1 回答 1

1

您问题中的代码是线程安全的恕我直言,但总的来说,该Interlocked.CompareExchange方法比Interlocked.Exchange实现无锁多线程的方法更灵活。以下是我希望对该方法进行编码的RunOnce方式:

int _lock; // 0: not acquired, 1: acquired

public void RunOnce()
{
    bool lockTaken = Interlocked.CompareExchange(ref _lock, 1, 0) == 0;
    if (!lockTaken) return;
    try
    {
        // Run code that should be executed by one thread only.
    }
    finally
    {
        bool lockReleased = Interlocked.CompareExchange(ref _lock, 0, 1) == 1;
        if (!lockReleased)
            throw new InvalidOperationException("Could not release the lock.");
    }
}

我的建议是使用Monitor该类:

object _locker = new();

public void RunOnce()
{
    bool lockTaken = Monitor.TryEnter(_locker);
    if (!lockTaken) return;
    try
    {
        // Run code that should be executed by one thread only.
    }
    finally { Monitor.Exit(_locker); }
}

...或SemaphoreSlim班级,如果您希望防止重入

SemaphoreSlim _semaphore = new(1, 1);

public void RunOnce()
{
    bool lockTaken = _semaphore.Wait(0);
    if (!lockTaken) return;
    try
    {
        // Run code that should be executed by one thread only.
    }
    finally { _semaphore.Release(); }
}

恕我直言,它使您的代码更清晰。

于 2021-08-03T01:20:42.250 回答