在C#中处理同步
过对指定对象的加锁和解锁可以实现同步代码段的访问。
在.NET的System.Threading命名空间中提供了Monitor类来实现加锁与解锁。该类中的方法都是静态的。
如下表:
C#中 lock关键字提供了与Monitoy.Enter和Monitoy.Exit同样的功能,这种方法用在你的代码段不能被其他独立的线程中断的情况。通过对Monitor类的简易封装,lock为同步访问变量提供了一个非常简单的方式,其用法如下:
lock(x)
{
// 使用x的语句
}
lock语句把变量放在圆括号中,以包装对象,称为独占锁或排它锁。当执行带有lock关键字的复合语句时,独占锁会保留下来。当变量被包装在独占锁中时,其他线程就不能访问该变量。如果在上面的代码中使用独占锁,在执行复合语句时,这个线程就会失去其时间片。如果下一个获得时间片的线程试图访问变量,就会被拒绝。Windows会让其他线程处于睡眠状态,直到解除了独占锁为止。
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
using System;
using System.Threading;
namespace ConsoleApplication2
{
class Account
{
int balance; // 余额
Random r = new Random();
public Account(int initial)
{
balance = initial;
}
// 取钱
int Withdraw(int amount)
{
if (balance < 0)
throw new Exception("余额为负!");
lock (this)
{
if (balance >= amount)
{
Console.WriteLine("原有余额: " + balance);
Console.WriteLine("支取金额: -" + amount);
balance = balance - amount;
Console.WriteLine("现有余额: " + balance);
return amount;
}
else
{
return 0; // 拒绝交易
}
}
}
// 测试交易
public void DoTransactions()
{
// 支取随机的金额100次
for (int i = 0; i < 100; i++)
{
Withdraw(r.Next(1, 100));
}
}
}
class TestApp
{
public static void Main()
{
// 建立10个线程同时进行交易
Thread[] threads = new Thread[10];
Account acc = new Account(100000000);
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(acc.DoTransactions));
threads[i] = t;
}
for (int i = 0; i < 10; i++)
{
threads[i].Start();
}
}
}
}