什么是线程同步?线程同步的应用场景有哪些?在C#中有哪些线程同步方式?下面对这些问题做一个总结,让大家在面试的时候遇到这些问题能够游刃有余。
线程同步是指在多线程环境下,多个线程同时访问共享资源时,确保数据一致性和正确性的一种机制。以下是线程同步的主要应用场景和常用方式,以及每种方式的简单代码示例。
应用场景
- 共享资源的保护
- 多个线程同时读写共享资源时,防止数据竞争和不一致。
- 线程间的通信
- 一个线程等待另一个线程完成某些任务或传递数据。
- 避免死锁
- 多线程并发访问资源时,通过合理设计同步机制,避免资源争用导致的死锁。
- 线程协调
- 控制线程的执行顺序或实现生产者-消费者模式。
线程同步方式与示例
- 锁(lock / Monitor)
用于同步对共享资源的访问,确保同时只有一个线程可以访问资源。
class Program
{
private static readonly object _lock = new object();
private static int _counter = 0;
static void Main()
{
Thread t1 = new Thread(IncrementCounter);
Thread t2 = new Thread(IncrementCounter);
t1.Start();
t2.Start();
t1.Join();
t2.Join();
Console.WriteLine($"Final Counter: {_counter}");
}
static void IncrementCounter()
{
for (int i = 0; i < 1000; i++)
{
lock (_lock)
{
_counter++;
}
}
}
}
- 信号量(Semaphore / SemaphoreSlim)
用于限制对某些资源的访问线程数。
class Program
{
private static SemaphoreSlim _semaphore = new SemaphoreSlim(2);
static void Main()
{
for (int i = 1; i <= 5; i++)
{
int id = i;
new Thread(() => AccessResource(id)).Start();
}
}
static void AccessResource(int id)
{
Console.WriteLine($"Thread {id} is waiting to enter...");
_semaphore.Wait();
Console.WriteLine($"Thread {id} entered.");
Thread.Sleep(2000); // Simulating work
Console.WriteLine($"Thread {id} is leaving.");
_semaphore.Release();
}
}
- 互斥(Mutex)
用于跨进程同步资源。
class Program
{
private static Mutex _mutex = new Mutex();
static void Main()
{
for (int i = 1; i <= 3; i++)
{
new Thread(AccessResource).Start(i);
}
}
static void AccessResource(object id)
{
Console.WriteLine($"Thread {id} waiting for mutex...");
_mutex.WaitOne();
Console.WriteLine($"Thread {id} acquired mutex.");
Thread.Sleep(2000);
Console.WriteLine($"Thread {id} releasing mutex.");
_mutex.ReleaseMutex();
}
}
- 手动重置事件(ManualResetEvent)
允许一个线程通知其他线程可以继续。
class Program
{
private static ManualResetEvent _mre = new ManualResetEvent(false);
static void Main()
{
new Thread(WaitForSignal).Start();
Console.WriteLine("Main thread doing work...");
Thread.Sleep(2000);
Console.WriteLine("Signal other threads to proceed.");
_mre.Set();
}
static void WaitForSignal()
{
Console.WriteLine("Thread waiting for signal...");
_mre.WaitOne();
Console.WriteLine("Thread received signal!");
}
}
- 自动重置事件(AutoResetEvent)
每次调用 Set 后,自动重置为非信号状态。
class Program
{
private static AutoResetEvent _are = new AutoResetEvent(false);
static void Main()
{
new Thread(WaitForSignal).Start();
Console.WriteLine("Main thread doing work...");
Thread.Sleep(2000);
Console.WriteLine("Signal other thread to proceed.");
_are.Set();
}
static void WaitForSignal()
{
Console.WriteLine("Thread waiting for signal...");
_are.WaitOne();
Console.WriteLine("Thread received signal!");
}
}
- 信号量栅栏(Barrier)
允许多个线程到达某个同步点后再继续执行。
class Program
{
private static Barrier _barrier = new Barrier(3, b => Console.WriteLine("All threads reached barrier."));
static void Main()
{
for (int i = 1; i <= 3; i++)
{
new Thread(Work).Start(i);
}
}
static void Work(object id)
{
Console.WriteLine($"Thread {id} doing work...");
Thread.Sleep(new Random().Next(1000, 3000));
Console.WriteLine($"Thread {id} waiting at barrier.");
_barrier.SignalAndWait();
Console.WriteLine($"Thread {id} passed barrier.");
}
}
- 读写锁(ReaderWriterLockSlim)
提供多个线程的读操作,但写操作是互斥的。
class Program
{
private static ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
private static List<int> _data = new List<int>();
static void Main()
{
new Thread(ReadData).Start();
new Thread(WriteData).Start();
}
static void ReadData()
{
_lock.EnterReadLock();
try
{
Console.WriteLine($"Read thread reading data: {string.Join(", ", _data)}");
}
finally
{
_lock.ExitReadLock();
}
}
static void WriteData()
{
_lock.EnterWriteLock();
try
{
_data.Add(new Random().Next(100));
Console.WriteLine("Write thread updated data.");
}
finally
{
_lock.ExitWriteLock();
}
}
}
以上是常用的线程同步方式及其简单示例代码,您可以根据具体需求选择合适的方式来保证线程安全。希望对大家有所帮助。