多个线程同时去访问同一个变量,此时会有冲突。解决方案:锁。
class MyThreadObject
{
private int state = 5;
public void ChangeState()
{
state++;
if (state==5)
{
Console.WriteLine("state=5");
Thread.Sleep(500);
}
state = 5;
}
}
有上面这个任务,用来修改state,如果state==5则打印。否则置5。
单一执行上面的方法不会打印m=5。
static void Main(string[] args)
{
MyThreadObject m = new MyThreadObject();
Thread th = new Thread(ChangeState);
th.Start(m);
Thread th2 = new Thread(ChangeState);
th2.Start(m);
}
static void ChangeState(object o)
{
MyThreadObject m = o as MyThreadObject;
while (true)
{
m.ChangeState();
}
}
此时两个任务轮流调用修改m的值。所以会一直输出m=5。对同一个资源两个任务相互干扰。
加上锁之后
static void Main(string[] args)
{
MyThreadObject m = new MyThreadObject();
Thread th = new Thread(ChangeState);
th.Start(m);
Thread th2 = new Thread(ChangeState);
th2.Start(m);
}
static void ChangeState(object o)
{
MyThreadObject m = o as MyThreadObject;
while (true)
{
lock(m) // 向系统申请可不可以锁定对象,
// 如果m对象没有被锁定,那么可以锁定并使用。
// 如果m对象被锁定了,那么这个语句会暂停,直到申请到m对象。
{
Console.WriteLine("得到锁。");
m.ChangeState();
}
Thread.Sleep(500);
Console.WriteLine("释放锁。");
}
}
lock会向系统申请资源,如果申请到,那么在线程结束之前不会释放资源,如果线程结束了,就会释放资源。防止在该线程使用期间被其他线程干扰。
死锁:
两个任务对lock的征询顺序不同,Task1在征询s1时,如果可用,就lock。如果此时Task2在此时征询s2,如果可用也lock掉,此时,两个任务谁都无法顺利执行下去。
public void SomeMethodOrTask1(object s1, object s2)
{
while (true)
{
lock (s1)
{
lock (s2)
{
s1.doSomething();
s2.doSomething();
}
}
}
}
public void SomeMethodOrTask2(object s1, object s2)
{
while (true)
{
lock (s2)
{
lock (s1)
{
s1.doSomething();
s2.doSomething();
}
}
}
}
解决方案:设计好锁定的顺序。