多线程的锁
1.Monitor类
Monitor.Enter和Monitor.Exit; 锁静态对象,类级的。并行的线程,串行的获得资源。
用法:
class Program { static void Main(string[] args) { for (int i = 0; i < 10; i++) { Thread t = new Thread(Run); t.Start(); } } //资源 static object obj = new object(); static int count = 0; static void Run() { Thread.Sleep(10); //进入临界区 Monitor.Enter(obj); Console.WriteLine("当前数字:{0}", ++count); //退出临界区 Monitor.Exit(obj); } }
Monitor.Wait 和Monitor.Pulse
Wait:暂时释放资源锁,该线程进入“等待队列”中。
Pulse:唤醒“等待队列”中的线程,被唤醒的线程(被wait的)重新获得资源。
二、ReaderWriterLock类
Monitor类实现的是资源在读写两种情况的临界区中只可以让一个线程访问,ReaderWriterLock类实现“写入串行,读取并行”。
<1> AcquireWriterLock: 获取写入锁。
ReleaseWriterLock:释放写入锁。
<2> AcquireReaderLock: 获取读锁。
ReleaseReaderLock:释放读锁。
<3> UpgradeToWriterLock:将读锁转为写锁。
DowngradeFromWriterLock:将写锁还原为读锁。
写法如下:
namespace Test { class Program { static List<int> list = new List<int>(); static ReaderWriterLock rw = new System.Threading.ReaderWriterLock(); static void Main(string[] args) { Thread t1 = new Thread(AutoAddFunc); Thread t2 = new Thread(AutoReadFunc); t1.Start(); t2.Start(); Console.Read(); } /// <summary> /// 模拟3s插入一次 /// </summary> /// <param name="num"></param> public static void AutoAddFunc() { //3000ms插入一次 Timer timer1 = new Timer(new TimerCallback(Add), null, 0, 3000); } public static void AutoReadFunc() { //1000ms自动读取一次 Timer timer1 = new Timer(new TimerCallback(Read), null, 0, 1000); Timer timer2 = new Timer(new TimerCallback(Read), null, 0, 1000); Timer timer3 = new Timer(new TimerCallback(Read), null, 0, 1000); } public static void Add(object obj) { var num = new Random().Next(0, 1000); //写锁 rw.AcquireWriterLock(TimeSpan.FromSeconds(30)); list.Add(num); Console.WriteLine("我是线程{0},我插入的数据是{1}。", Thread.CurrentThread.ManagedThreadId, num); //释放锁 rw.ReleaseWriterLock(); } public static void Read(object obj) { //读锁 rw.AcquireReaderLock(TimeSpan.FromSeconds(30)); Console.WriteLine("我是线程{0},我读取的集合为:{1}", Thread.CurrentThread.ManagedThreadId, string.Join(",", list)); //释放锁 rw.ReleaseReaderLock(); } } }