争用条件
对于两个异步执行的线程,如果同时请求同一个对象,会造成读取数据出现问题。
首先,定义一个类:
class MyThreadObject
{
private int state = 5;
public void ChangeState()
{
state++;
if (state == 5) Console.WriteLine("State is 5!");
state = 5;
}
按照这个方法来看,肯定是没有输出的。
只有一个线程时
class Program
{
static void myChangeState(object o)
{
MyThreadObject m = o as MyThreadObject;
while (true)
{
m.ChangeState();
}
}
static void Main(string[] args)
{
MyThreadObject m = new MyThreadObject();
Thread t1 = new Thread(myChangeState);
t1.Start(m);
Console.ReadKey();
}
}
此时,是没有输出的。
两个线程异步执行
class Program
{
static void myChangeState(object o)
{
MyThreadObject m = o as MyThreadObject;
while (true)
{
m.ChangeState();
}
}
static void Main(string[] args)
{
MyThreadObject m = new MyThreadObject();
Thread t1 = new Thread(myChangeState);
Thread t2 = new Thread(myChangeState);
t1.Start(m);
t2.Start(m);
Console.ReadKey();
}
}
这时,程序会不断的输出:State is 5!
原因也很简单,一个线程在判断语句处时,另一个线程可能又将state的值改为了5,而导致输出合法。
通过加锁来实现互斥
class Program
{
static void myChangeState(object o)
{
MyThreadObject m = o as MyThreadObject;
while (true)
{
lock(m)//申请一个锁
{
m.ChangeState();
}//自动释放锁
}
}
static void Main(string[] args)
{
MyThreadObject m = new MyThreadObject();
Thread t1 = new Thread(myChangeState);
Thread t2 = new Thread(myChangeState);
t1.Start(m);
t2.Start(m);
Console.ReadKey();
}
}
使用lock()方法来加一个锁,这样程序就没有输出了。
需要注意的是,lock只能锁定对象,即引用类型,不能锁定值类型。
死锁问题
不赘述了,非常常规的概念。
想要避免这个问题,就要在设计锁的阶段就考虑好锁的顺序。