当我们确认某个类的例子在同一时刻只能被一个线程访问时,我们可以直接将类标识成Synchronization的,这样,CLR会自动对这个类实行同步模式,实际上,这上面涉及到同步域的概念,当类按如下设计时,我们可以保证类的例子能够被多个线程同时访问
1).在类的声明中,添加System.Runtime.Remoting.Contexts.SynchronizationAttribute属性。
2). 继承至System.ContextBoundObject
需要切记的是,要推动上述措施,类需要继承至System.ContextBoundObject,换句话说,类需要是上下文绑定的。
一个示范类代码如下:
Code
[System.Runtime.Remoting.Contexts.Synchronization]
publicclassSynchronizedClass : System.ContextBoundObject
{
}
八、MethodImplAttribute
如果临界区是跨越整个方式的,也就是说,整个步骤内部的代码都应该上锁的话,使用MethodImplAttribute属性会更简洁一些。这样就不用在步骤内部加锁了,只应该在原则里面加上 [MethodImpl(MethodImplOptions.Synchronized)] 就可以了,MehthodImpl和MethodImplOptions都在命名空间System.Runtime.CompilerServices里面。但要切记这个属性会使整个步骤加锁,直到技巧返回,才释放锁。因此,使用上不太灵活。如果要提早释放锁,则需要使用Monitor或lock。我们来看一个例子:

Code
[MethodImpl(MethodImplOptions.Synchronized)]
publicvoidDoSomeWorkSync()
{
Console.WriteLine("DoSomeWorkSync() -- Lock held by Thread"+
Thread.CurrentThread.GetHashCode());
Thread.Sleep(1000);
Console.WriteLine("DoSomeWorkSync() -- Lock released by Thread"+
Thread.CurrentThread.GetHashCode());
}
publicvoidDoSomeWorkNoSync()
{
Console.WriteLine("DoSomeWorkNoSync() -- Entered Thread is"+
Thread.CurrentThread.GetHashCode());
Thread.Sleep(1000);
Console.WriteLine("DoSomeWorkNoSync() -- Leaving Thread is"+
Thread.CurrentThread.GetHashCode());
}
[STAThread]
staticvoidMain(string[] args)
{

MethodImplAttr testObj=newMethodImplAttr();
Thread t1=newThread(newThreadStart(testObj.DoSomeWorkNoSync));
Thread t2=newThread(newThreadStart(testObj.DoSomeWorkNoSync));
t1.Start();
t2.Start();
Thread t3=newThread(newThreadStart(testObj.DoSomeWorkSync));
Thread t4=newThread(newThreadStart(testObj.DoSomeWorkSync));
t3.Start();
t4.Start();
Console.ReadLine();
}

这里,我们有两个方法,我们可以对比一下,一个是加了属性MethodImpl的DoSomeWorkSync(),一个是没加的DoSomeWorkNoSync()。在方式中Sleep(1000)是为了在第一个线程还在方法中时,第二个线程才能有足够的时间进来。对每个步骤分别起了两个线程,我们先来看一下结果:

可以看出,对于线程1和2,也就是调用没有加属性的方式的线程,当线程2进入方式后,还没有离开,线程1有过来了,这就是说,方法没有同步。我们再来说说线程3和4,当线程3进来后,方法被锁,直到线程3释放了锁之后,线程4才进来。
九、同步事件和期待句柄
用lock和Monitor可以较好地起到线程同步的作用c# 多线程 syncroot,但他们能够推动线程之间释放事件。如果要推动线程同步的同时,线程之间需要有交互,就要用到同步事件。同步事件是有两个状态(终止和非终止)的对象,它可以拿来激活和挂起线程。
同步事件有两种:AutoResetEvent和ManualResetEvent。它们之间唯一不同的地方就是在激活线程以后,状态能否自动由解除变为非终止。AutoResetEvent自动变为非终止,就是说一个AutoResetEvent只能激活一个线程。而ManualResetEvent要直到它的Reset方法被调用,状态才变为非终止,在这之前,ManualResetEvent可以激活任意多个线程。
可以调用WaitOne、WaitAny或WaitAll来使线程等待事件。它们之间的差别可以查看MSDN。当调用事件的Set方法时,事件将变为终止状态,等待的线程被唤醒。
来看一个例子,这个示例是MSDN上的。因为事件只用于一个线程的激活,所以使用AutoResetEvent或ManualResetEvent类都可以。

Code
staticAutoResetEvent autoEvent;
staticvoidDoWork()
{
Console.WriteLine("worker thread started, now waiting on event
");
autoEvent.WaitOne();
Console.WriteLine("worker thread reactivated, now exiting
");
}
[STAThread]
staticvoidMain(string[] args)
{
autoEvent=newAutoResetEvent(false);
Console.WriteLine("main thread starting worker thread
");
Thread t=newThread(newThreadStart(DoWork));
t.Start();
Console.WriteLine("main thrad sleeping for 1 second
");
Thread.Sleep(1000);
Console.WriteLine("main thread signaling worker thread
");
autoEvent.Set();
Console.ReadLine();
}

我们先来看一下输出:

在主函数中,首先建立一个AutoResetEvent的例子,参数false表示初始状况为非终止,如果是true的话,初始状况则为解除。然后建立并开启一个子线程,在子线程中,通过读取AutoResetEvent的WaitOne方法,使子线程等待指定事件的出现。然后主线程等待一秒后,调用AutoResetEvent的Set方法,使状况由非终止变为终止,重新激活子线程。
参考:
1/MSDN((VS.80).aspx)
2/http://www.cnblogs.com/VincentWP/archive/2008/06/25/1229104.html
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-124836-2.html
到现在潮水般的旅日
显然一个统一的中华民族必然比目前的分裂状态下的内耗更好
再看你是什么反应