C# 语言 线程同步与锁机制

C#阿木 发布于 2025-06-12 13 次阅读


C 线程同步与锁机制详解

在多线程编程中,线程同步与锁机制是确保数据一致性和程序正确性的关键。C 提供了丰富的线程同步工具,包括互斥锁(Mutex)、信号量(Semaphore)、读写锁(ReaderWriterLock)等。本文将围绕 C 语言中的线程同步与锁机制进行深入探讨。

随着计算机硬件的发展,多核处理器越来越普及,多线程编程成为提高程序性能的重要手段。多线程编程也带来了线程同步和数据一致性的问题。为了保证程序的正确性和效率,我们需要合理地使用线程同步与锁机制。

线程同步概述

线程同步是指多个线程在执行过程中,按照一定的顺序执行,以避免出现数据竞争和资源冲突。在 C 中,线程同步可以通过以下几种方式实现:

1. 互斥锁(Mutex)
2. 信号量(Semaphore)
3. 读写锁(ReaderWriterLock)
4. Monitor
5. SemaphoreSlim

互斥锁(Mutex)

互斥锁是一种最基本的线程同步机制,用于确保同一时间只有一个线程可以访问共享资源。在 C 中,可以使用 `Mutex` 类来实现互斥锁。

csharp
using System;
using System.Threading;

class Program
{
static Mutex mutex = new Mutex();

static void Main()
{
Thread t1 = new Thread(DoWork);
Thread t2 = new Thread(DoWork);

t1.Start();
t2.Start();

t1.Join();
t2.Join();
}

static void DoWork()
{
mutex.WaitOne();
Console.WriteLine("线程 {0} 正在执行...", Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
Console.WriteLine("线程 {0} 执行完毕", Thread.CurrentThread.ManagedThreadId);
mutex.ReleaseMutex();
}
}

在上面的代码中,我们创建了一个 `Mutex` 对象,并在 `DoWork` 方法中使用 `WaitOne` 和 `ReleaseMutex` 方法来确保同一时间只有一个线程可以执行该方法。

信号量(Semaphore)

信号量是一种更高级的线程同步机制,它可以允许多个线程同时访问共享资源,但总数不超过指定的数量。在 C 中,可以使用 `Semaphore` 类来实现信号量。

csharp
using System;
using System.Threading;

class Program
{
static Semaphore semaphore = new Semaphore(2, 2);

static void Main()
{
Thread t1 = new Thread(DoWork);
Thread t2 = new Thread(DoWork);
Thread t3 = new Thread(DoWork);

t1.Start();
t2.Start();
t3.Start();

t1.Join();
t2.Join();
t3.Join();
}

static void DoWork()
{
semaphore.WaitOne();
Console.WriteLine("线程 {0} 正在执行...", Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
Console.WriteLine("线程 {0} 执行完毕", Thread.CurrentThread.ManagedThreadId);
semaphore.Release();
}
}

在上面的代码中,我们创建了一个 `Semaphore` 对象,其初始信号量为 2,最大信号量也为 2。这意味着同一时间最多有两个线程可以执行 `DoWork` 方法。

读写锁(ReaderWriterLock)

读写锁允许多个线程同时读取共享资源,但写入操作需要独占访问。在 C 中,可以使用 `ReaderWriterLock` 类来实现读写锁。

csharp
using System;
using System.Threading;

class Program
{
static ReaderWriterLock rwLock = new ReaderWriterLock();

static void Main()
{
Thread t1 = new Thread(ReadData);
Thread t2 = new Thread(ReadData);
Thread t3 = new Thread(WriteData);

t1.Start();
t2.Start();
t3.Start();

t1.Join();
t2.Join();
t3.Join();
}

static void ReadData()
{
rwLock.AcquireReaderLock(1000);
Console.WriteLine("线程 {0} 正在读取数据...", Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
Console.WriteLine("线程 {0} 读取完毕", Thread.CurrentThread.ManagedThreadId);
rwLock.ReleaseReaderLock();
}

static void WriteData()
{
rwLock.AcquireWriterLock(1000);
Console.WriteLine("线程 {0} 正在写入数据...", Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
Console.WriteLine("线程 {0} 写入完毕", Thread.CurrentThread.ManagedThreadId);
rwLock.ReleaseWriterLock();
}
}

在上面的代码中,我们创建了一个 `ReaderWriterLock` 对象,并分别使用 `AcquireReaderLock` 和 `AcquireWriterLock` 方法来获取读锁和写锁。

总结

本文介绍了 C 语言中的线程同步与锁机制,包括互斥锁、信号量、读写锁等。通过合理地使用这些机制,我们可以确保程序的正确性和效率。在实际开发中,应根据具体需求选择合适的线程同步机制,以达到最佳的性能和可靠性。