当多个线程在并发的时候,难免会碰到相互冲突的事情,比如最经典的ATM机的问题,并发不可怕,可怕的是我们没有能力控制。
线程以我的理解可以分为三种
① 锁。
② 互斥。
③ 信号。
好,这一篇主要整理“锁”,C#提供了2种手工控制的锁
一: Monitor类
这个算是实现锁机制的纯正类,在锁定的临界区中只允许让一个线程访问,其他线程排队等待。主要整理为2组方法。
1:Monitor.Enter和Monitor.Exit
微软很照护我们,给了我们语法糖Lock,对的,语言糖确实减少了我们不必要的劳动并且让代码更可观,但是如果我们要精细的
控制,则必须使用原生类,这里要注意一个问题就是“锁住什么”的问题,一般情况下我们锁住的都是静态对象,我们知道静态对象
属于类级别,当有很多线程共同访问的时候,那个静态对象对多个线程来说是一个,不像实例字段会被认为是多个。
2:Monitor.Wait和Monitor.Pulse
首先这两个方法是成对出现,通常使用在Enter,Exit之间。
Wait: 暂时的释放资源锁,然后该线程进入”等待队列“中,那么自然别的线程就能获取到资源锁。
Pulse: 唤醒“等待队列”中的线程,那么当时被Wait的线程就重新获取到了锁。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
Thread t = new Thread(run);
t.Start();
}
Console.ReadKey();
}
static object obj = new object();
static int count = 0;
static void run()
{
Thread.Sleep(10);
Monitor.Enter(obj);
Console.WriteLine(++count);
Monitor.Exit(obj);
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace Test
{
public class Program
{
public static void Main(string[] args)
{
LockObj obj = new LockObj();
//注意,这里使用的是同一个资源对象obj
Jack jack = new Jack(obj);
John john = new John(obj);
Thread t1 = new Thread(new ThreadStart(jack.Run));
Thread t2 = new Thread(new ThreadStart(john.Run));
t1.Start();
t1.Name = "Jack";
t2.Start();
t2.Name = "John";
Console.ReadLine();
}
}
//锁定对象
public class LockObj { }
public class Jack
{
private LockObj obj;
public Jack(LockObj obj)
{
this.obj = obj;
}
public void Run()
{
Monitor.Enter(this.obj);
Console.WriteLine("{0}:今天我值班吗?看下", Thread.CurrentThread.Name);
Console.WriteLine("{0}:原来是jon值班呀,那我走呀", Thread.CurrentThread.Name);
//暂时的释放锁资源
Monitor.Wait(this.obj);
Console.WriteLine("{0}:那行吧", Thread.CurrentThread.Name);
//唤醒等待队列中的线程
Monitor.Pulse(this.obj);
Console.WriteLine("{0}:呵呵", Thread.CurrentThread.Name);
Monitor.Exit(this.obj);
}
}
public class John
{
private LockObj obj;
public John(LockObj obj)
{
this.obj = obj;
}
public void Run()
{
Monitor.Enter(this.obj);
Console.WriteLine("{0}:哥们,今天我有点事情,你帮我下呗",
Thread.CurrentThread.Name);
//唤醒等待队列中的线程
Monitor.Pulse(this.obj);
Console.WriteLine("{0}:谢谢兄弟了", Thread.CurrentThread.Name);
//暂时的释放锁资源
Monitor.Wait(this.obj);
Console.WriteLine("{0}:哈哈", Thread.CurrentThread.Name);
Monitor.Exit(this.obj);
}
}
}