一、基本介绍
锁是一种同步机制,用于控制多个线程对共享资源的访问。当一个线程获得了锁时,其他线程将被阻塞,直到该线程释放了锁。
在并发编程中,多个线程同时访问共享资源可能导致数据竞争和不确定的行为。锁可以确保在任意时刻只有一个线程可以访问共享资源,从而避免竞态条件和数据不一致性问题。
二、锁的作用原理
锁的作用原理通常涉及到内部的互斥机制。当一个线程获得锁时,它会将锁标记为已被占用,其他线程尝试获取该锁时会被阻塞,直到持有锁的线程释放锁。这种互斥机制可以通过不同的算法和数据结构来实现,如互斥量、自旋锁等。
三、常用的线程锁机制
1. lock
语句
lock
语句是C#中最基本的同步机制,它使用一个对象作为锁(通常称为“锁对象”),确保同一时间只有一个线程可以执行锁定代码块。
using System;
using System.Threading;
class Program
{
static object lockObject = new object();
static int sharedResource = 0;
static void Main()
{
Thread thread1 = new Thread(Increment);
Thread thread2 = new Thread(Increment);
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
Console.WriteLine($"Final value: {sharedResource}");
}
static void Increment()
{
for (int i = 0; i < 10000; i++)
{
lock (lockObject)
{
sharedResource++;
}
}
}
}
2. Monitor
类
Monitor
类提供了更灵活的锁定机制,它允许等待、通知和超时等高级功能。
using System;
using System.Threading;
class Program
{
static object lockObject = new object();
static int sharedResource = 0;
static void Main()
{
Thread thread1 = new Thread(Increment);
Thread thread2 = new Thread(Increment);
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
Console.WriteLine($"Final value: {sharedResource}");
}
static void Increment()
{
for (int i = 0; i < 10000; i++)
{
bool lockTaken = false;
try
{
Monitor.Enter(lockObject, ref lockTaken);
sharedResource++;
}
finally
{
if (lockTaken)
{
Monitor.Exit(lockObject);
}
}
}
}
}
3. Mutex
类
Mutex
类是一种跨进程的同步机制,但它也可以用于线程同步。Mutex
可以被不同的进程或线程持有。
using System;
using System.Threading;
class Program
{
static Mutex mutex = new Mutex();
static void Main()
{
Thread thread1 = new Thread(Increment);
Thread thread2 = new Thread(Increment);
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
Console.WriteLine($"Final value: {sharedResource}");
}
static int sharedResource = 0;
static void Increment()
{
for (int i = 0; i < 10000; i++)
{
bool lockTaken = false;
try
{
mutex.WaitOne(); // 请求锁
lockTaken = true;
sharedResource++;
}
finally
{
if (lockTaken)
{
mutex.ReleaseMutex(); // 释放锁
}
}
}
}
}
4. Semaphore
类
Semaphore
类允许多个线程同时访问资源,但它限制了同时访问的最大线程数。
using System;
using System.Threading;
class Program
{
static Semaphore semaphore = new Semaphore(1, 1);
static int sharedResource = 0;
static void Main()
{
Thread thread1 = new Thread(Increment);
Thread thread2 = new Thread(Increment);
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
Console.WriteLine($"Final value: {sharedResource}");
}
static void Increment()
{
for (int i = 0; i < 10000; i++)
{
semaphore.WaitOne(); // 请求信号量
try
{
sharedResource++;
}
finally
{
semaphore.Release(); // 释放信号量
}
}
}
}
5. ReaderWriterLockSlim
类
ReaderWriterLockSlim
类提供了一种机制,允许多个读者同时访问资源,但写者在写入时会独占访问。
using System;
using System.Threading;
class Program
{
static ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
static int sharedResource = 0;
static void Main()
{
Thread reader1 = new Thread(Read);
Thread reader2 = new Thread(Read);
Thread writer = new Thread(Write);
reader1.Start();
reader2.Start();
writer.Start();
reader1.Join();
reader2.Join();
writer.Join();
Console.WriteLine($"Final value: {sharedResource}");
}
static void Read()
{
rwLock.EnterReadLock();
try
{
Console.WriteLine($"Reader reading: {sharedResource}");
}
finally
{
rwLock.ExitReadLock();
}
}
static void Write()
{
rwLock.EnterWriteLock();
try
{
sharedResource++;
Console.WriteLine($"Writer updated: {sharedResource}");
}
finally
{
rwLock.ExitWriteLock();
}
}
}