c# 多執行緒環境下控制對共享資源訪問的辦法

我只吃饭不洗碗發表於2024-07-29
  1. Monitor:
    • 定義:Monitor 是 C# 中最基本的同步機制,透過 EnterExit 方法來控制對共享資源的訪問。它提供了排他鎖的功能,確保在任何時刻只有一個執行緒可以訪問共享資源。
    • 優點:簡單易用,適合對臨界區進行粗粒度的同步控制。
    • 缺點:只能實現排它鎖,不能實現讀寫鎖,效能相對較低。

  

c# 多執行緒環境下控制對共享資源訪問的辦法
class Program
{
    static readonly object _lock = new object();
    static int _counter = 0;

    static void Main()
    {
        for (int i = 0; i < 10; i++)
        {
            new Thread(IncrementCounter).Start();
        }

        Console.ReadKey();
    }

    static void IncrementCounter()
    {
        Monitor.Enter(_lock);
        try
        {
            _counter++;
            Console.WriteLine($"Counter: {_counter}");
        }
        finally
        {
            Monitor.Exit(_lock);
        }
    }
}
Monitor

  1. Mutex:
    • 定義:Mutex 是一個作業系統物件,用於在程序間共享,透過 WaitOneReleaseMutex 來控制對共享資源的訪問。它提供了程序間的同步能力。
    • 優點:可跨程序使用,適合在程序間進行同步。
    • 缺點:相比 Monitor,效能開銷較大,因為涉及到系統呼叫。

  

c# 多執行緒環境下控制對共享資源訪問的辦法
class Program
{
    static Mutex _mutex = new Mutex();
    static int _counter = 0;

    static void Main()
    {
        for (int i = 0; i < 10; i++)
        {
            new Thread(IncrementCounter).Start();
        }

        Console.ReadKey();
    }

    static void IncrementCounter()
    {
        _mutex.WaitOne();
        _counter++;
        Console.WriteLine($"Counter: {_counter}");
        _mutex.ReleaseMutex();
    }
}
Mutex

  1. ReaderWriterLockSlim:
    • 定義:ReaderWriterLockSlim 實現了讀寫分離鎖,允許多個執行緒同時讀取共享資源,但只允許一個執行緒寫入共享資源。這種機制適用於讀多寫少的場景。
    • 優點:適合讀多寫少的場景,提高了併發效能。
    • 缺點:相對複雜,可能會引起死鎖,不支援遞迴鎖。

  

c# 多執行緒環境下控制對共享資源訪問的辦法
class Program
{
    static ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();
    static int _counter = 0;

    static void Main()
    {
        for (int i = 0; i < 5; i++)
        {
            new Thread(ReadCounter).Start();
            new Thread(IncrementCounter).Start();
        }

        Console.ReadKey();
    }

    static void ReadCounter()
    {
        _rwLock.EnterReadLock();
        Console.WriteLine($"Counter: {_counter}");
        _rwLock.ExitReadLock();
    }

    static void IncrementCounter()
    {
        _rwLock.EnterWriteLock();
        _counter++;
        Console.WriteLine($"Counter incremented to: {_counter}");
        _rwLock.ExitWriteLock();
    }
}
ReaderWriterLockSlim

  1. Semaphore:
    • 定義:Semaphore 是一個訊號量,用於控制同時訪問共享資源的執行緒數量。透過 WaitOneRelease 方法,可以控制訪問資源的執行緒數量。
    • 優點:可以控制多個執行緒同時訪問共享資源的數量,靈活性較高。
    • 缺點:相對於其他機制,使用起來較為複雜,需要謹慎處理訊號量的釋放。

  

c# 多執行緒環境下控制對共享資源訪問的辦法
class Program
{
    static Semaphore _semaphore = new Semaphore(2, 2); // Allow 2 threads to access the resource simultaneously
    static int _counter = 0;

    static void Main()
    {
        for (int i = 0; i < 5; i++)
        {
            new Thread(IncrementCounter).Start();
        }

        Console.ReadKey();
    }

    static void IncrementCounter()
    {
        _semaphore.WaitOne();
        _counter++;
        Console.WriteLine($"Counter: {_counter}");
        _semaphore.Release();
    }
}
Semaphore

  1. SemaphoreSlim:
    • 定義:SemaphoreSlim 是輕量級的訊號量,與 Semaphore 類似,用於控制同時訪問共享資源的執行緒數量,但相比 Semaphore 更輕量級。
    • 優點:相比 SemaphoreSemaphoreSlim 的開銷更小,適用於資源訪問頻繁的場景。
    • 缺點:與 Semaphore 相比,功能上略有限制,例如沒有 Release(Int32) 方法,只能遞增訊號量一個單位。
c# 多執行緒環境下控制對共享資源訪問的辦法
class Program
{
    static SemaphoreSlim _semaphore = new SemaphoreSlim(2, 2); // Allow 2 threads to access the resource simultaneously
    static int _counter = 0;

    static void Main()
    {
        for (int i = 0; i < 5; i++)
        {
            new Thread(IncrementCounter).Start();
        }

        Console.ReadKey();
    }

    static void IncrementCounter()
    {
        _semaphore.Wait();
        _counter++;
        Console.WriteLine($"Counter: {_counter}");
        _semaphore.Release();
    }
}
SemaphoreSlim

  1. lock:
    • 定義:lock 是 C# 中的關鍵字,用於在程式碼塊級別實現互斥鎖,保護共享資源不被多個執行緒同時訪問。
    • 優點:簡單易用,適合對臨界區進行細粒度的同步控制,編寫起來比較方便。
    • 缺點:只能用於單執行緒內部的同步,不能跨越執行緒或程序,如果不小心使用會導致死鎖。
c# 多執行緒環境下控制對共享資源訪問的辦法
class Program
{
    static readonly object _lock = new object();
    static int _counter = 0;

    static void Main()
    {
        for (int i = 0; i < 5; i++)
        {
            new Thread(IncrementCounter).Start();
        }

        Console.ReadKey();
    }

    static void IncrementCounter()
    {
        lock (_lock)
        {
            _counter++;
            Console.WriteLine($"Counter: {_counter}");
        }
    }
}
lock

相關文章