多线程学习-线程同步,lock初探
时间:2010-10-01 来源:伊羽
为了防止共享资源被多个线程破坏,就必须在代码中使用线程同步结构。
比如现在有一个计数器,每次访问都加1
public sealed class NormalCounter
{
Int32 num = 0;
public void Add()
{
num++;
}
public Int32 GetNumber
{
get
{
return num;
}
}
}
现在有3个不同的用户同时访问这个计数器(3个线程)
public class TestNormalCounter
{
public void StartWithMultiThread()
{
new Thread(() => { JustDoIt(); }).Start();
new Thread(() => { JustDoIt(); }).Start();
new Thread(() => { JustDoIt(); }).Start();
}
void JustDoIt()
{
NormalCounter counter = new NormalCounter();
for (Int32 i = 0; i < 5; i++)
{
counter.Add();
Console.WriteLine(String.Concat("由ID是:", Thread.CurrentThread.ManagedThreadId, " 的线程输出当前值:", counter.GetNumber));
}
}
}
最后结果如下:
并没有达到计数器的效果,这是因为创建了3个实例,系统分配了3块内存分别进行了计数。
为了避免这种情况,就要线程同步结构。
public sealed class SingletonCounter
{
static SingletonCounter counter = null;
static readonly Object thislock = new Object();
Int32 num = 0;
SingletonCounter() { }
public static SingletonCounter GetCounter
{
get
{
if (null == counter)
{
lock (thislock)
{
counter = new SingletonCounter();
}
}
return counter;
}
}
public void Add()
{
num++;
}
public Int32 GetNumber
{
get
{
return num;
}
}
}
//测试代码跟前一实例一样
这里用到了双检锁技巧来保证整个程序中,只有一个SingletonCounter实例,这样计数器便能正确的运行
(这里用到了单例设计模式,单例设计模式实际只需要用静态初始化,或者嵌套类延时初始化就可以简单的实现,这里只是演示如何使用lock来做同步)
结果如下:
lock 确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。
通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。常见的结构 lock (this)、lock (typeof (MyType)) 和 lock ("myLock") 违反此准则:
如果实例可以被公共访问,将出现 lock (this) 问题。
如果 MyType 可以被公共访问,将出现 lock (typeof (MyType)) 问题。
由于进程中使用同一字符串的任何其他代码将共享同一个锁,所以出现 lock(“myLock”) 问题。
最佳做法是定义 private 对象来锁定, 或 private static 对象变量来保护所有实例所共有的数据。










