什么是线程互斥?

线程互斥(Thread Mutua lExclusion)是一种同步机制,用于确保在多线程环境中,同一时间只有一个线程可以访问特定的资源或代码段。线程互斥的主要目的是防止多个线程同时修改共享数据,从而避免数据不一致和竞态条件(Race Conditions)。

什么是竞态条件(Race Conditions)?
竞态条件是指程序的输出或行为取决于多个线程执行顺序的情况。当多个线程同时访问和修改共享资源时,如果没有适当的同步机制,可能会导致不可预测的结果。

线程互斥的主要机制:
在 C# 中,有多种机制可以实现线程互斥,以下是常见的几种:

  1. Mutex(互斥体):Mutex 是一种同步基元,可以用于线程间的互斥访问。Mutex 可以是局部的(仅在当前进程内有效)或全局的(跨多个进程有效)。

    using System;
    using System.Threading;

    public class MutexExample
    {
    private static Mutex _mutex;

    public static void Main()
    {
    _mutex = new Mutex();

    // 创建两个线程
    Thread thread1 = new Thread(DoWork);
    Thread thread2 = new Thread(DoWork);

    thread1.Start();
    thread2.Start();

    // 等待线程完成
    thread1.Join();
    thread2.Join();

    _mutex.Close();
    }

    public static void DoWork()
    {
    Console.WriteLine($"线程 {Thread.CurrentThread.ManagedThreadId} 尝试获取 Mutex");
    _mutex.WaitOne(); // 获取 Mutex
    Console.WriteLine($"线程 {Thread.CurrentThread.ManagedThreadId} 获取到 Mutex");

    // 执行临界区代码
    Thread.Sleep(1000);
    Console.WriteLine($"线程 {Thread.CurrentThread.ManagedThreadId} 释放 Mutex");

    _mutex.ReleaseMutex(); // 释放 Mutex
    }
    }

  2. Semaphore(信号量):Semaphore 是一种同步基元,允许指定数量的线程同时访问共享资源。信号量可以是局部的或全局的。

    using System;
    using System.Threading;

    public class SemaphoreExample
    {
    private static Semaphore _semaphore;

    public static void Main()
    {
    _semaphore = new Semaphore(2, 2); // 允许 2 个线程同时访问

    // 创建多个线程
    for (int i = 0; i < 5; i++)
    {
    Thread thread = new Thread(DoWork);
    thread.Start(i);
    }

    // 等待所有线程完成
    Thread.Sleep(5000);
    }

    public static void DoWork(object state)
    {
    int id = (int)state;
    Console.WriteLine($"线程 {id} 尝试获取 Semaphore");
    _semaphore.WaitOne(); // 获取 Semaphore
    Console.WriteLine($"线程 {id} 获取到 Semaphore");

    // 执行临界区代码
    Thread.Sleep(1000);
    Console.WriteLine($"线程 {id} 释放 Semaphore");

    _semaphore.Release(); // 释放 Semaphore
    }
    }

  3. SemaphoreSlim(轻量级信号量):适用于在单个应用程序或进程内使用。

    using System;
    using System.Threading;

    public class SemaphoreSlimExample
    {
    private static SemaphoreSlim _semaphoreSlim;

    public static void Main()
    {
    _semaphoreSlim = new SemaphoreSlim(2, 2); // 允许 2 个线程同时访问

    // 创建多个线程
    for (int i = 0; i < 5; i++)
    {
    Thread thread = new Thread(DoWork);
    thread.Start(i);
    }

    // 等待所有线程完成
    Thread.Sleep(5000);
    }

    public static void DoWork(object state)
    {
    int id = (int)state;
    Console.WriteLine($"线程 {id} 尝试获取 SemaphoreSlim");
    _semaphoreSlim.Wait(); // 获取 SemaphoreSlim
    Console.WriteLine($"线程 {id} 获取到 SemaphoreSlim");

    // 执行临界区代码
    Thread.Sleep(1000);
    Console.WriteLine($"线程 {id} 释放 SemaphoreSlim");

    _semaphoreSlim.Release(); // 释放 SemaphoreSlim
    }
    }

  4. Lock 语句:适用于单个应用程序或进程内使用。

    using System;
    using System.Threading;

    public class LockExample
    {
    private static readonly object _lock = new object();

    public static void Main()
    {
    // 创建多个线程
    for (int i = 0; i < 5; i++)
    {
    Thread thread = new Thread(DoWork);
    thread.Start(i);
    }

    // 等待所有线程完成
    Thread.Sleep(5000);
    }

    public static void DoWork(object state)
    {
    int id = (int)state;
    Console.WriteLine($"线程 {id} 尝试获取 Lock");

    lock (_lock) // 获取 Lock
    {
    Console.WriteLine($"线程 {id} 获取到 Lock");

    // 执行临界区代码
    Thread.Sleep(1000);
    Console.WriteLine($"线程 {id} 释放 Lock");
    }
    }
    }

  5. Monitor 类:提供了更高级的同步机制,可以实现 lock 语句的功能,并且提供了更多的控制选项。

    using System;
    using System.Threading;

    public class MonitorExample
    {
    private static readonly object _lock = new object();

    public static void Main()
    {
    // 创建多个线程
    for (int i = 0; i < 5; i++)
    {
    Thread thread = new Thread(DoWork);
    thread.Start(i);
    }

    // 等待所有线程完成
    Thread.Sleep(5000);
    }

    public static void DoWork(object state)
    {
    int id = (int)state;
    Console.WriteLine($"线程 {id} 尝试获取 Monitor");

    Monitor.Enter(_lock); // 获取 Monitor
    try
    {
    Console.WriteLine($"线程 {id} 获取到 Monitor");

    // 执行临界区代码
    Thread.Sleep(1000);
    Console.WriteLine($"线程 {id} 释放 Monitor");
    }
    finally
    {
    Monitor.Exit(_lock); // 释放 Monitor
    }
    }
    }

  6. ReaderWriterLockSlim 类:允许多个线程同时进行读操作,但只允许一个线程进行写操作。适用于读操作频繁而写操作较少的场景。

    using System;
    using System.Threading;

    public class ReaderWriterLockSlimExample
    {
    private static readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();
    private static int _sharedResource = 0;

    public static void Main()
    {
    // 创建多个读线程
    for (int i = 0; i < 5; i++)
    {
    Thread thread = new Thread(ReadResource);
    thread.Start(i);
    }

    // 创建多个写线程
    for (int i = 0; i < 5; i++)
    {
    Thread thread = new Thread(WriteResource);
    thread.Start(i);
    }

    // 等待所有线程完成
    Thread.Sleep(5000);
    }

    public static void ReadResource(object state)
    {
    int id = (int)state;
    Console.WriteLine($"读线程 {id} 尝试获取读锁");

    _rwLock.EnterReadLock();
    try
    {
    Console.WriteLine($"读线程 {id} 获取到读锁");
    Console.WriteLine($"读线程 {id} 读取资源值: {_sharedResource}");
    Thread.Sleep(500);
    Console.WriteLine($"读线程 {id} 释放读锁");
    }
    finally
    {
    _rwLock.ExitReadLock();
    }
    }

    public static void WriteResource(object state)
    {
    int id = (int)state;
    Console.WriteLine($"写线程 {id} 尝试获取写锁");

    _rwLock.EnterWriteLock();
    try
    {
    Console.WriteLine($"写线程 {id} 获取到写锁");
    _sharedResource++;
    Console.WriteLine($"写线程 {id} 写入资源值: {_sharedResource}");
    Thread.Sleep(1000);
    Console.WriteLine($"写线程 {id} 释放写锁");
    }
    finally
    {
    _rwLock.ExitWriteLock();
    }
    }
    }

posted @ 2024-12-27 17:00  似梦亦非梦  阅读(214)  评论(0)    收藏  举报