You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中用volatile避免竞态条件是否合理?特定场景如何选型?

Volatile vs. Locks/Monitor in C#: Avoiding Race Conditions

Great question—volatile is a keyword that trips up a lot of C# developers because it’s often misused as a silver bullet for thread safety. Let’s break this down clearly.

Is using volatile a good practice to avoid race conditions?

Short answer: No, not on its own.

volatile only addresses one aspect of thread safety: visibility. It ensures that reads from the variable always pull the latest value from main memory (instead of a CPU cache), and writes are immediately flushed to main memory. But race conditions happen when multiple threads are modifying or checking-modifying shared state in an uncoordinated way—volatile does nothing to prevent concurrent execution of critical code paths or make non-atomic operations atomic.

In other words, volatile stops threads from working with stale data, but it doesn’t stop them from stepping on each other’s toes when they interact with that data.

Your specific scenario: Is volatile enough for the isAvailable flag?

Absolutely not. Let’s look at your code again:

private bool isAvailable;
private void foo() { 
    if(isAvailable) { 
        isAvailable = false; 
        DoSomething(); 
        isAvailable = true; 
    } 
}

Even if you mark isAvailable as volatile, here’s what can happen in a multi-threaded environment:

  1. Thread A reads isAvailable as true.
  2. Before Thread A can set isAvailable to false, Thread B also reads isAvailable as true.
  3. Both threads enter the if block, set isAvailable to false, and execute DoSomething() at the same time.

This is a classic race condition—volatile ensures both threads see the latest value, but it doesn’t prevent them from checking the value and acting on it simultaneously. The check-and-set operation (if(isAvailable) { isAvailable = false; }) is not atomic, so volatile can’t fix that.

What should you use instead?

You need a way to enforce exclusive access to the critical section (the code inside the if block). Two reliable options:

1. lock (or Monitor)

This is the most straightforward approach for this scenario. A lock guarantees that only one thread can execute the enclosed code at a time:

private readonly object _lockObj = new object();
private bool isAvailable = true;

private void foo() { 
    lock(_lockObj) {
        if(isAvailable) { 
            isAvailable = false;
            try {
                DoSomething();
            }
            finally {
                isAvailable = true;
            }
        }
    }
}

Using finally ensures isAvailable gets reset to true even if DoSomething() throws an exception—critical for keeping your service available after failures.

2. Atomic operations with Interlocked

If you want a lighter-weight alternative (though lock is already very efficient for short code paths), you can use Interlocked methods to perform atomic check-and-set operations. Since bool can’t be used directly with Interlocked, we can use an int (1 = available, 0 = unavailable):

private int isAvailable = 1; // 1 = available, 0 = unavailable

private void foo() { 
    // Atomically check if isAvailable is 1, and set it to 0 if so
    if(Interlocked.CompareExchange(ref isAvailable, 0, 1) == 1) {
        try {
            DoSomething();
        }
        finally {
            // Atomically set it back to 1
            Interlocked.Exchange(ref isAvailable, 1);
        }
    }
}

CompareExchange ensures that the check and set happen in a single atomic operation, so no two threads can successfully enter the block at the same time.

Final takeaway

volatile is useful for scenarios where you only need to ensure visibility (e.g., a flag that’s set by one thread and read by others, with no check-modify-write cycles). But for your scenario—where you need to prevent concurrent execution of DoSomething()—you must use a lock, Monitor, or atomic operations to eliminate the race condition.

内容的提问来源于stack exchange,提问作者Luka Kovac

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:42:38