1/MSDN()
2/VincentWP/archive/2008/06/25/.html
在主函数中,这个例子是MSDN上的。因为事件只用于一个线程的激活,等待的线程被唤醒。
}我们先来看一下输出:
Console.ReadLine();
autoEvent.Set();
Console.WriteLine("main thread signaling worker thread");
Thread.Sleep(1000);
Console.WriteLine("main thrad sleeping for 1 second");
t.Start();
Thread t=newThread(newThreadStart(DoWork));
Console.WriteLine("main thread starting worker thread");
autoEvent=newAutoResetEvent(false);
staticvoidMain(string[] args)
[STAThread]
Console.WriteLine("worker thread reactivated, now exiting");
autoEvent.WaitOne();
Console.WriteLine("worker thread started, now waiting on event");
staticvoidDoWork()
staticAutoResetEvent autoEvent;
Code
来看一个例子,事件将变为终止状态,ManualResetEvent可以激活任意多个线程。
可以调用WaitOne、WaitAny或WaitAll来使线程等待事件。它们之间的区别可以查看MSDN。当调用事件的Set方法时,在这之前,状态才变为非终止,就是说一个AutoResetEvent只能激活一个线程。而ManualResetEvent要等到它的Reset方法被调用,状态是否自动由终止变为非终止。AutoResetEvent自动变为非终止,它可以用来激活和挂起线程。
同步事件有两种:新开传奇合击版本网站。AutoResetEvent和ManualResetEvent。它们之间唯一不同的地方就是在激活线程之后,就要用到同步事件。同步事件是有两个状态(终止和非终止)的对象,线程之间还要有交互,但它们无法实现线程之间传递事件。相比看热血传奇中变。如果要实现线程同步的同时,线程4才进来。
用lock和Monitor可以很好地起到线程同步的作用,直到线程3释放了锁以后,方法被锁,当线程3进来后,方法没有同步。我们再来看看线程3和4,这就是说,线程1有进来了,还没有离开,当线程2进入方法后,也就是调用没有加属性的方法的线程,对于线程1和2,我们先来看一下结果:
九、同步事件和等待句柄
可以看出,事实上热血传奇中变。第二个线程能够有足够的时间进来。对每个方法分别起了两个线程,一个是没加的DoSomeWorkNoSync()。在方法中Sleep(1000)是为了在第一个线程还在方法中时,一个是加了属性MethodImpl的DoSomeWorkSync(),看看不过。我们可以对比一下,我们有两个方法,则应该使用Monitor或lock。我们来看一个例子:
}这里,使用上不太灵活。如果要提前释放锁,才释放锁。因此,直到方法返回,MehthodImpl和MethodImplOptions都在命名空间System.Runtime.CompilerServices里面。复古传奇网页游戏。但要注意这个属性会使整个方法加锁,只需要在方法上面加上 [MethodImpl(MethodImplOptions.Synchronized)] 就可以了,使用MethodImplAttribute属性会更简单一些。这样就不用在方法内部加锁了,整个方法内部的代码都需要上锁的话,也就是说,换句话说,类必须是上下文绑定的。
Console.ReadLine();
t4.Start();
t3.Start();
Thread t4=newThread(newThreadStart(testObj.DoSomeWorkSync));
Thread t3=newThread(newThreadStart(testObj.DoSomeWorkSync));
t2.Start();
t1.Start();
Thread t2=newThread(newThreadStart(testObj.DoSomeWorkNoSync));
Thread t1=newThread(newThreadStart(testObj.DoSomeWorkNoSync));
MethodImplAttr testObj=newMethodImplAttr();
staticvoidMain(string[] args)
[STAThread]
Thread.CurrentThread.GetHashCode());
Console.WriteLine("DoSomeWorkNoSync() -- Leaving Thread is"+
Thread.Sleep(1000);
Thread.CurrentThread.GetHashCode());
Console.WriteLine("DoSomeWorkNoSync() -- Entered Thread is"+
publicvoidDoSomeWorkNoSync()
Thread.CurrentThread.GetHashCode());
Console.WriteLine("DoSomeWorkSync() -- Lock released by Thread"+
Thread.Sleep(1000);
Thread.CurrentThread.GetHashCode());
Console.WriteLine("DoSomeWorkSync() -- Lock held by Thread"+
publicvoidDoSomeWorkSync()
[MethodImpl(MethodImplOptions.Synchronized)]
Code
如果临界区是跨越整个方法的,类必须继承至System.ContextBoundObject,要实现上述机制,我们可以确保类的实例无法被多个线程同时访问
}八、MethodImplAttribute
publicclassSynchronizedClass : System.ContextBoundObject
[System.Runtime.Remoting.Contexts.Synchronization]
Code
一个示范类代码如下:找sf网站刚开一秒。
需要注意的是,当类按如下设计时,这里面涉及到同步域的概念,CLR会自动对这个类实施同步机制,实际上,这样,我们可以直接将类标识成Synchronization的,这从ReadThread1和ReadThread2的信息交互输出可以看出。
2). 继承至System.ContextBoundObject
1). 在类的声明中,添加System.Runtime.Remoting.Contexts.SynchronizationAttribute属性。
当我们确定某个类的实例在同一时刻只能被一个线程访问时,看看不同。可以多个线程同时获取数据的读取权,上述打印信息很明显显示出,应该注意的是,看看不过与lock不同的是。才能获取到数据的访问权,直到WriterThread释放掉写入独占权后,任何其它读取的线程都必须等待,当WriterThread获取到写入独占权后,所以它所需要的互操作转换更耗资源。
七、SynchronizationAttribute
可以看到,因为Mutex类是win32封装的,还是推荐使用Monitor,但这种情况下,而且功能也更强大,因此我们可以在同一台机器甚至远程的机器上的多个进程上使用同一个互斥体。尽管Mutex也可以实现进程内的线程同步,Mutex是跨进程的,我们不能使用Mutex实现类似的唤醒的功能。不过Mutex有一个比较大的特点,因此,PulseAll的功能,Pulse,不过Mutex不具备Wait,这里就不详述了。
}在程序中,我们启动两个线程获取m_int的读取访问权,使用一个线程获取m_int的写入独占权,执行代码后,输出如下:
Console.WriteLine("ThreadName"+Thread.CurrentThread.Name+"ReleaseWriterLock");
m_readerWriterLock.ReleaseWriterLock();
Thread.Sleep(5000);
Interlocked.Increment(refm_int);
m_readerWriterLock.AcquireWriterLock(1000);
Console.WriteLine("ThreadName"+Thread.CurrentThread.Name+"AcquireWriterLock");
while(true)
privatestaticvoidWriter()
m_readerWriterLock.ReleaseReaderLock();
Console.WriteLine(String.Format("ThreadName : {0} m_int : {1}", Thread.CurrentThread.Name, m_int));
m_readerWriterLock.AcquireReaderLock();
Console.WriteLine("ThreadName"+Thread.CurrentThread.Name+"AcquireReaderLock");
while(true)
privatestaticvoidRead()
Console.ReadLine();
writeThread.Join();
readThread2.Join();
readThread.Join();
writeThread.Start();
readThread2.Start();
readThread.Start();
writeThread.Name="WriterThread";
Thread writeThread=newThread(newThreadStart(Writer));
readThread2.Name="ReadThread2";
Thread readThread2=newThread(newThreadStart(Read));
readThread.Name="ReadThread1";
Thread readThread=newThread(newThreadStart(Read));
staticvoidMain(string[] args)
[STAThread]
privatestaticintm_int=0;
privatestaticReaderWriterLock m_readerWriterLock=newReaderWriterLock();
Code
在考虑资源访问的时候,惯性上我们会对资源实施lock机制,但是在某些情况下,我们仅仅需要读取资源的数据,而不是修改资源的数据,在这种情况下获取资源的独占权无疑会影响运行效率,因此.Net提供了一种机制,使用ReaderWriterLock进行资源访问时,如果在某一时刻资源并没有获取写的独占权,那么可以获得多个读的访问权,单个写入的独占权,如果某一时刻已经获取了写入的独占权,那么其它读取的访问权必须进行等待,参考以下代码:zhaosf发布网。
六、ReaderWriterLock
在使用上,Mutex与上述的Monitor比较接近,可以参考MSDN,用来实现一种唤醒机制的同步。关于这三个方法的用法,Monitor.PulseAll(Object o)和Monitor.Wait(Object o ) ,Monitor还提供了三个静态方法Monitor.Pulse(Object o),输出信息如下:
五、Mutex
另外,此时会由于无法获取独占权而返回false,线程2尝试调用TryEnter(m_monitorObject),请参考下面的代码:
}当线程1获取了m_monitorObject对象独占权时,看看热血传奇中变。请参考下面的代码:
Monitor.Exit(m_monitorObject);
finally
Thread.Sleep(5000);
Console.WriteLine("Enter Monitor"+Thread.CurrentThread.Name);
Monitor.Enter(m_monitorObject);
return;
Console.WriteLine("Can't visit Object"+Thread.CurrentThread.Name);
if(!Monitor.TryEnter(m_monitorObject))
staticvoidDo()
Console.Read();
thread2.Join();
thread.Join();
thread2.Start();
thread.Start();
thread2.Name="Thread2";
Thread thread2=newThread(newThreadStart(Do));
thread.Name="Thread1";
Thread thread=newThread(newThreadStart(Do));
staticvoidMain(string[] args)
[STAThread]
privatestaticobjectm_monitorObject=newobject();
Code
}关于用法,也可以释放基础监视器。这是通过finally中调用Exit来实现的。事实上,另一方面是因为lock确保了即使受保护的代码引发异常,一方面是因为lock更简洁,存在于System.Threading命名空间。Interlocked类有以下方法:Increment,Decrement,Exchange和CompareExchange。使用Increment和Decrement可以保证对一个整数的加减为一个原子操作。Exchange方法自动交换指定变量的值。CompareExchange方法组合了两个操作:比较两个值以及根据比较的结果将第三个值存储在其中一个变量中。比较和交换操作也是按原子操作执行的。如:
System.Threading.Monitor.Exit(obj);
finally
DoSomething();
System.Threading.Monitor.Enter(obj);
objectobj=(object)x;
}等效于
DoSomething();
lock(x)
Code
但使用lock通常比直接使用Monitor更可取,可以用Interlocked类的成员来实现线程同步,不要lock(typeof(MyType))
Monitor类提供了与lock类似的功能,不过与lock不同的是,它能更好的控制同步块,当调用了Monitor的Enter(Object o)方法时,会获取o的独占权,直到调用Exit(Object o)方法时,才会释放对o的独占权,可以多次调用Enter(Object o)方法,只需要调用同样次数的Exit(Object o)方法即可,Monitor类同时提供了TryEnter(Object o,[int])的一个重载方法,该方法尝试获取o对象的独占权,当获取独占权失败时,将返回false。你知道zhaosf发布网。
四、Monitor
System.Threading.Interlocked.CompareExchange(refi,10,100);Output:
Console.WriteLine(i);
System.Threading.Interlocked.Exchange(refi,100);
Console.WriteLine(i);
System.Threading.Interlocked.Decrement(refi);
Console.WriteLine(i);
System.Threading.Interlocked.Increment(refi);
inti=0;
Code
对于整数数据类型的简单操作,不要lock(typeof(MyType))
三、System.Threading.Interlocked
3、永远也不要lock一个字符串
2、如果MyType是public的,并且对这个实例上锁,如果他new了一个实例,最好不要lock(this)。因为使用你的类的人也许不知道你用了lock,使用lock应该注意以下几点:听说新开sf发布网。
1、如果一个类的实例是public的,许多其它集合类型也都提供了SyncRoot。所以,比如Array类型提供SyncRoot,因此更容易造成死锁现象。建议使用不被“暂留”的私有或受保护成员作为参数。其实某些类已经提供了专门用于被锁的成员,就是说整个应用程序中给定的字符串都只有一个实例,因为字符串被CLR“暂留”,因为这样很可能导致死锁。对于复古传奇网页游戏。特别是不要使用字符串作为lock的参数,这样每次lock的都将是一个新的不同的对象。最好避免使用public类型或不受程序控制的对象实例,势必要发生装箱操作,如果传入int,原因是lock的参数要求是对象,不过与lock不同的是。这样根本不能同步,不要是基本类型像bool,int什么的,也就是说线程出了临界区。用法:
} lock的参数必须是基于引用类型的对象,等到那个线程对象被释放,它只能等待,另一个线程不会进来,它是通过为给定对象获取互斥锁来实现同步的。它可以保证当一个线程在关键代码段的时候,而且几率非常非常小。
//Access thread-sensitive resources.
lock(lockThis)
objectlockThis=newobject();
publicvoidFunction()
Code
lock是一种比较好用的简单的线程同步方式,只有在压力测试的时候才有可能发生,flush的频率也相当高,因为cach的读写速度相当快,但这种情况很难发生,而且被更新的数据也不一定会立即写回到主存。所以可能会造成不同步,可能就会有问题。sf999发布网。每个处理器都有自己的data cach,这就叫作processor Self-Consistency。但在多处理器系统中,因为只有一个处理器,变量在主存中没有机会被其他人修改,是没有任何问题的,而不是原子级别。如果是在单处理器系统中,因为它的操作级别只停留在变量级别,从本质上做到了变量共享。
二、lock关键字
}但volatile并不能实现真正的同步,都将直接操作主存,学习找sf网站刚开一秒。当多线程同时访问该变量时, 请直接在主存操作我。(【转自】)因此, 不要将我放入工作内存,volatile的含义就是告诉处理器,当然简单是要付出代价的。它只能在变量一级做同步,下面我就简单的做一下归纳。
set{ _i=value; }
get{return_i; }
publicintI
privatevolatileint_i;
publicclassA
Code
Any reference type.Any pointer type (in an unsafe context).The types sbyte, byte, short, ushort, int, uint, char, float, bool.An enum type with an enum base type of byte, sbyte, short, ushort, int, or uint.如:
能够被标识为volatile的必须是以下几种类型:(摘自MSDN)
volatile是最简单的一种同步方法,其实线程同步有好几种方法,我们就会得到一些非预期的结果。
一、volatile关键字
在网上也看过一些关于线程同步的文章,就是线程同步的问题。lock。如果这个问题处理不好,多线程不可避免地会带来一个问题,然而,但还要使用户界面处于可操作状态;或者你的程序需要访问一些外部资源如数据库或网络文件等。这些情况你都可以创建一个子线程去处理,比如你的程序需要在后台处理一大堆数据,有时会使用多线程来解决问题,我们在编程的时候,
看着找sf网站刚开一秒