1.在不同的代码片段使用同一个锁,这两个代码片段只能被获得锁的线程访问,其他线程不能访问。
namespace 同一个锁测试
{
class Program
{
private static object obj1 = new object();
public static int count = 0;
static void Main(string[] args)
{
Thread t1 = new Thread(() =>
{
while (true)
{
Function1();
}
});
Thread t2 = new Thread(() =>
{
while (true)
{
Function2();
}
});
t1.Start();
t2.Start();
}
private static void Function1()
{
lock (obj1)
{
count++;
Console.WriteLine("thread1:count is " + count);
Thread.Sleep(500);
}
}
private static void Function2()
{
lock (obj1)
{
count++;
Console.WriteLine("thread2:count is " + count);
Thread.Sleep(500);
}
}
}
}
输出结果:
从结果可以看到:Function1和Function2函数同一时刻,不能被不同线程同时执行。说明同一个锁被用于多处时,只能由获得锁的线程访问,其他线程不能访问。
2.死锁的发生:当两段代码使用锁的顺序不一致时,容易发生死锁
namespace LockTest
{
class Program
{
private static object obj1 = new object();
private static object obj2 = new object();
public static int count = 0;
static void Main(string[] args)
{
Thread t1 = new Thread(() =>
{
while (true)
{
Function1();
}
});
Thread t2 = new Thread(() =>
{
while (true)
{
Function2();
}
});
t1.Start();
t2.Start();
}
private static void Function1()
{
lock (obj1)
{
lock (obj2)
{
count++;
Console.WriteLine("thread1:count is "+count);
}
}
}
private static void Function2()
{
lock (obj2)
{
lock (obj1)
{
count++;
Console.WriteLine("thread2:count is " + count);
}
}
}
}
}
运行结果如下:
可以看到输出了一句话然后就卡住了。
原因:线程t1进入Function1方法后获得obj1的锁,同一时刻,线程t2进入Function2方法获得obj2的锁。然后t1等待获得了obj2的锁才能执行(obj2的锁被t2占住了),t2等待获得obj1的锁才能执行(obj1的锁被t1占住了),所以两个互相等待对方释放锁,结果出现无限的等待的死锁现象。
3.同一个线程可以获得同一个锁多次,但是也必须释放多次,释放次数必须和获得次数相同
使用lock时,当进入“{”时获得锁,退出“}”时自动释放锁,不需要我们去关心锁的释放,好比我们使用using实现了IDispose接口的对象一样。但是某些情况下我们要使用Monitor.Enter/Monitor.Exit方法。
namespace Lock同一个对象多次释放一次
{
class Program
{
private static object obj1 = new object();
public static int count = 0;
static void Main(string[] args)
{
Thread t1 = new Thread(() =>
{
while (true)
{
Function();
Thread.Sleep(500);
}
});
t1.Name = "t1";
Thread t2 = new Thread(() =>
{
while (true)
{
Function();
Thread.Sleep(500);
}
});
t2.Name = "t2";
t1.Start();
t2.Start();
}
private static void Function()
{
Monitor.Enter(obj1);
Monitor.Enter(obj1);
count++;
Console.WriteLine("current thread is " + Thread.CurrentThread.Name);
Console.WriteLine("count is " + count);
Monitor.Exit(obj1);
//Monitor.Exit(obj1);
}
}
}
注意:最后一句Monitor.Exit(obj1)被注释掉了,运行结果如下:
Function函数只能被同一个线程执行说明线程t1获得了锁没有释放,所以t2执行不了。并且每多执行一次Function函数,t1就少释放obj1一次。
当将最后的Monitor.Exit(obj1)的注释取消后,代码如下:
private static void Function()
{
Monitor.Enter(obj1);
Monitor.Enter(obj1);
count++;
Console.WriteLine("current thread is " + Thread.CurrentThread.Name);
Console.WriteLine("count is " + count);
Monitor.Exit(obj1);
Monitor.Exit(obj1);
}
再次运行结果如下:
结果恢复正常,说明了上述的观点。