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

C#嵌套Parallel.For循环中的共享资源安全访问问题

Hey there! Let's walk through converting your nested for loops to Parallel.For and fixing that shared resource thread-safety issue—this is a super common pitfall when moving to parallel code, so you’re in the right place.

Step 1: Convert Nested Loops to Parallel.For

First, let’s get the basic parallel structure down. Your original nested loop looks like this:

int sharedResource = 0;
for (int i = 0; i < someMax; i++) 
{
    for (int j = 0; j < someInnerMax; j++) 
    {
        // Your core logic here
        sharedResource++; // Example unsafe operation
    }
}

Converting this to nested Parallel.For is straightforward, but we can’t just swap for with Parallel.For and call it a day—because that shared resource access will cause race conditions. Here’s the skeleton first:

int sharedResource = 0;
Parallel.For(0, someMax, i => 
{
    Parallel.For(0, someInnerMax, j => 
    {
        // Core logic goes here
        // WARNING: Directly modifying sharedResource here is UNSAFE!
    });
});

Step 2: Fix Shared Resource Thread Safety

Since sharedResource is an int, the simplest and most efficient way to handle thread-safe updates is using the System.Threading.Interlocked class. It provides atomic operations that prevent race conditions without the overhead of a full lock (great for simple increment/decrement operations).

For example, instead of sharedResource++, use Interlocked.Increment(ref sharedResource):

int sharedResource = 0;
Parallel.For(0, someMax, i => 
{
    Parallel.For(0, someInnerMax, j => 
    {
        // Your core per-item logic here
        // Safe atomic increment
        Interlocked.Increment(ref sharedResource);
    });
});

If your operation on sharedResource is more complex than a simple increment/decrement (like adding a variable value, or conditional updates), you can use Interlocked.Add or Interlocked.CompareExchange for those cases. For example:

// Adding a value to sharedResource safely
int valueToAdd = CalculateSomeValue(i, j);
Interlocked.Add(ref sharedResource, valueToAdd);

When to Use lock Instead?

If your shared resource logic is too complex for Interlocked (like multiple steps that need to be atomic together), wrap the critical section in a lock statement. Just note that this adds more overhead, so use it only when necessary:

int sharedResource = 0;
object lockObj = new object(); // Dedicated lock object (never lock on sharedResource itself!)

Parallel.For(0, someMax, i => 
{
    Parallel.For(0, someInnerMax, j => 
    {
        // Non-critical logic here
        lock(lockObj)
        {
            // Critical section: only one thread can execute this at a time
            sharedResource += CalculateComplexValue(i, j);
            if (sharedResource > someThreshold)
            {
                sharedResource = someThreshold;
            }
        }
    });
});

Step 3: Optional: Optimize Granularity

You mentioned Parallel.For has better granularity—if your inner loop is very small (like only a few iterations per inner loop), you might get better performance by combining loops or using a custom partitioner to reduce overhead. For example, you could flatten the nested loops into a single Parallel.For over the total number of items:

int totalItems = someMax * someInnerMax;
int sharedResource = 0;

Parallel.For(0, totalItems, idx => 
{
    int i = idx / someInnerMax;
    int j = idx % someInnerMax;
    // Your core logic here
    Interlocked.Increment(ref sharedResource);
});

This can reduce the overhead of spinning up multiple inner parallel loops, especially if someInnerMax is small.

Final Notes

  • Always test your parallel code thoroughly—race conditions can be tricky to reproduce, so use tools like Visual Studio’s thread debugger or unit tests with high concurrency to catch issues.
  • If sharedResource is something more complex than an int (like a collection), look into thread-safe collections from System.Collections.Concurrent (e.g., ConcurrentQueue, ConcurrentDictionary) instead of rolling your own locking.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:39:07