整数的无锁多线程

Lockless multithreading of an integer

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

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 是一个状态(即表示枚举的整数),是否会应用相同的机制?

你问题中的代码恕我直言是线程安全的,但总的来说 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 class:

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 class if you prefer to :

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(); }
}

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