一、概述
.NET提供了各种多线程同步锁:
- 同步锁基础:Monitor;
- 同步锁:lock;
- 跨进程锁:Mutex;
- 原子操作锁:Interlocked;
- 自旋锁:SpinLock;
二、Monitor
Monitor提供了同步访问对象的机制,通过成对的 Enter 和 Exit 方法对对象加锁。
static readonly object _locker = new object();
bool lockTaken = false;
try
{
Monitor.Enter (_locker, ref lockTaken);
// 你的代码...
}
finally { if (lockTaken) Monitor.Exit (_locker); }
Monitor也提供了一个TryEnter方法,允许指定获取锁的超时时间。
三、lock
lock是一个语法糖,其实际即为上述Monitor的同步代码,简化了使用锁的代码量。
static readonly object _locker = new object();
static int _val1, _val2;
static void Go()
{
lock (_locker)
{
if (_val2 != 0)
Console.WriteLine (_val1 / _val2);
_val2 = 0;
}
}
四、Mutex
Mutex 的作用与 lock 相似,不同的是 Mutex 支持跨进程工作,但是效率要比 lock 低。
Mutex 继承自 WaitHandle ,可使用 WaitIOne 方法加锁,使用 ReleaseMutex 方法释放锁。
static void Main()
{
// 命名的 Mutex 是机器范围的,它的名称需要是唯一的
// 比如使用公司名+程序名,或者也可以用 URL
using (var mutex = new Mutex (false, "oreilly.com OneAtATimeDemo"))
{
// 可能其它程序实例正在关闭,所以可以等待几秒来让其它实例完成关闭
if (!mutex.WaitOne (TimeSpan.FromSeconds (3), false))
{
Console.WriteLine ("Another app instance is running. Bye!");
return;
}
RunProgram();
}
}
static void RunProgram()
{
Console.WriteLine ("Running. Press Enter to exit");
Console.ReadLine();
}
五、Interlocked
Interlocked用于确保各个线程调用同一变量时的线程安全。
class Program
{
static long _sum;
static void Main()
{ // _sum
// 简单的自增/自减操作:
Interlocked.Increment (ref _sum); // 1
Interlocked.Decrement (ref _sum); // 0
// 加/减一个值:
Interlocked.Add (ref _sum, 3); // 3
// 读取64位字段:
Console.WriteLine (Interlocked.Read (ref _sum)); // 3
// 读取当前值并且写64位字段
// (打印 "3",并且将 _sum 更新为 10 )
Console.WriteLine (Interlocked.Exchange (ref _sum, 10)); // 10
// 仅当字段的当前值匹配特定的值(10)时才更新它:
Console.WriteLine (Interlocked.CompareExchange (ref _sum,
123, 10); // 123
}
}
参考链接: