Skillfully use the various methods of interlocked, and then no lock without blocking the situation to determine the completion status of all the threads.
Last night, I watched. CLR via C # 29th << Primitive Thread Synchronous construction >> Although this book is not the first time, but the previous look is around the area, no deep understanding, even can be said to not understand, internship and found their knowledge originally so surface, A lot of implementation can not be done, this has hit me to a large extent, and, spring recruit also quickly come, more need to play a solid foundation. What caught my attention was Jeffrey in the 29th chapter: using interlocked, the code is short, never blocks any threads, and two uses thread pool threads to achieve automatic scaling. Downloaded the source code, and then analyzed the following example in the book, Code as follows:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Net.Http;usingSystem.Text;usingSystem.Threading;usingSystem.Threading.Tasks;namespacevlr_via_cs{Internal Static classAsynccoordinatordemo { Public Static voidGo () {ConstInt32 Timeout =50000;//Change to desired timeoutMultiwebrequests act =Newmultiwebrequests (timeout); Console.WriteLine ("All operations initiated (timeout={0}). Hits <Enter> to cancel.", (timeout= = Timeout.infinite)?"Infinite": (timeout. ToString () +"Ms")); Console.ReadLine (); Act. Cancel (); Console.WriteLine (); Console.WriteLine ("Hit enter to terminate."); Console.ReadLine (); } Private Sealed classmultiwebrequests {//This helper class coordinates all the asynchronous operations PrivateAsynccoordinator M_ac =NewAsynccoordinator (); //Set of WEB servers we want to query & their responses (Exception or Int32) Privatedictionary<string, object> m_servers =NewDictionary<string, object> { { "http://cjjjs.com/",NULL }, { "http://cnblogs.com/",NULL }, { "http://www.jobbole.com/",NULL } }; PublicMultiwebrequests (Int32 timeout =timeout.infinite) {//asynchronously initiate all the requests @ once varHttpClient =NewHttpClient (); foreach(varServerinchm_servers. Keys) {M_ac. Abouttobegin (1); Httpclient.getbytearrayasync (server). ContinueWith (Task=Computeresult (server, Task)); } //Tell Asynccoordinator, all operations has been initiated and to call//Alldone when "operations complete", Cancel is called, or the timeout occursM_ac. Allbegun (alldone, timeout); } Private voidComputeresult (String server, task<byte[]>Task) {Object result; if(Task. Exception! =NULL) {result=task. Exception.innerexception; } Else { //Process I/O completion here on thread pool thread (s)//Put your own compute-intensive algorithm here ...result = task. Result.length;//This example just returns the length } //Save Result (exception/sum) and indicate that 1 operation completedM_servers[server] =result; M_ac. Justended (); } //Calling this method indicates the results don ' t matter anymore Public voidCancel () {M_ac. Cancel (); } //This method was called after all WEB servers respond,//Cancel is called, or the timeout occurs Private voidalldone (coordinationstatus status) {Switch(status) { CaseCoordinationStatus.Cancel:Console.WriteLine ("operation canceled."); Break; CaseCoordinationStatus.Timeout:Console.WriteLine ("Operation Timed-out."); Break; CaseCoordinationStatus.AllDone:Console.WriteLine ("operation completed; results below:"); foreach(varServerinchm_servers) {Console.Write ("{0}", server. Key); Object result=server. Value; if(Result isException) {Console.WriteLine ("failed due to {0}.", result. GetType (). Name); } Else{Console.WriteLine ("returned {0:n0} bytes.", result); } } Break; } } } Private enumcoordinationstatus {alldone, Timeout, Cancel}; Private Sealed classAsynccoordinator {PrivateInt32 M_opcount =1;//decremented when Allbegun calls justended PrivateInt32 m_statusreported =0;//0=false, 1=true PrivateAction<coordinationstatus>M_callback; PrivateTimer M_timer; //This method must is called before initiating an operation Public voidAbouttobegin (Int32 Opstoadd =1) {Interlocked.add (refM_opcount, Opstoadd); } //This method must is called after a operations result has been processed Public voidjustended () {if(Interlocked.decrement (refM_opcount) = =0) Reportstatus (Coordinationstatus.alldone); } //This method must is called after initiating all operations Public voidAllbegun (action<coordinationstatus> callback, Int32 timeout =timeout.infinite) {m_callback=callback; if(Timeout! =timeout.infinite) {//invokes the callback function at the specified point in time (Duetime) and then invokes the callback function at the specified time interval (period)M_timer =NewTimer (timeexpired,NULL, timeout, timeout.infinite); } justended (); } //working with outdated threads Private voidtimeexpired (Object o) {reportstatus (coordinationstatus.timeout); } Public voidCancel () {if(M_callback = =NULL) Throw NewInvalidOperationException ("Cancel cannot be called before Allbegun"); Reportstatus (Coordinationstatus.cancel); } Private voidreportstatus (coordinationstatus status) {if(M_timer! =NULL) { //If timer is still on play, kill itTimer timer = Interlocked.exchange (refM_timer,NULL); if(Timer! =NULL) timer. Dispose (); } //If status has never been reported, report it; else ignore it if(Interlocked.exchange (refM_statusreported,1) ==0) M_callback (status); } } } classProgram {Static voidMain (string[] args) {Asynccoordinatordemo.go (); Console.read (); } }}
It is a lock-free operation, the Interlocked method is an atomic operation in user mode, for the CPU, not the thread memory, and it is spin-waiting, consuming CPU resources. Analysis of the next Asynccoordinator class, mainly using the Interlocked Add method, real-time count of the number of threads, and then a thread to run the last call interlocked decrement method of self-reduction. If you pay attention, you will find that most of the concurrent judgments currently use the interlocked methods, especially the CompareExchange method in the anything mode of interlocked, here to mention a mouth, Except for the return value of the CompareExchange and Exchange methods, which return the value of the original ref type, the rest of the methods return the value after the change. Finally, we can use the Allbegun method to determine whether all the threads are executed, and then set the state variable m_statusreported to 1 to prevent the state from being judged.
This class is very good, before writing concurrency, always worry how to determine whether concurrency has been done, and do not want to use blocking, this class is very good, of course, applied to specific projects may also need to change, but the basic model is this, unchanged.
A bit of emotion: good things need our own to explore, before the producer consumer model, Java code A lot of, Leng did not see a few C #, even if there is also simple, although you can change Java to C #, but a bit of emotion C # technology stack and less resources
Use interlocked to perform atomic operations under multiple threads, without locking and blocking to implement thread run state judgment