[Windows] thread mantalk -- monitor and lock for. Net thread synchronization [windows] thread mantalk -- slim read/write lock for Thread Synchronization

Source: Internet
Author: User
Tags mscorlib net thread

Abstract: this series is intended to record knowledge points of windwos threads, including thread basics, thread scheduling, thread synchronization, TLS, and thread pool.

Starting from this article, I started to summarize the thread synchronization method on the. NET platform and compare the native API methods of windows. You can find the contact.

 

Monitor and lock in. net

I believe many spectators are already familiar with this. This article is summativeArticle, Some sections will compare the relationship between monitor and key segments. Since lock is the monitor, we should start with the monitor. Generally, the monitor is used as follows:

 
Monitor. Entry (lockobj); try {// synchronization zone of lockobj} catch (exception e) {// Exception HandlingCode} Finally {monitor. Exit (lockobj); // unlock}

When a thread returns the value of monitor. entry, it obtains the access permission for lockobj. Other threads that attempt to obtain the value of lockobj are blocked until the thread calls monitor. Exit to release the ownership of lockobj. This means the following three points:

    • If lockobj is idle, the first thread that calls the entry will immediately obtain lockobj;
    • If the thread that calls the entry has been authorized to access lockobj, it will not be blocked;
    • If lockobj is locked by another thread when the entry is called, the thread waits until lockobj is unlocked;

In fact, the second point is an important feature, which will happen in recursion. Monitor should record the number of times that the thread is allowed to access lockobj to correctly decrease the number of locks.

I spent some time studying the underlying implementation method of monitor, but I did not find any evidence to prove that monitor is related to key segments. However, in terms of representation, monitor APIs are similar to key segments, and the three features are almost identical. Moreover, msdn also expresses monitor as a critical section. Therefore, for the time being, monitor is the packaging of key segments!

In my previous article [windows] thread discussion-the key section of thread synchronization, I described in detail the key section of Windows API. The following lists the comparison of the two APIs:

. Net Monitor API Windows API
Monitor. Entry (lockobj) Entercriticalsection (& CS)
Monitor. Exit (lockobj) Leavecriticalsection (& CS)
Monitor. tryentry (lockobj) Tryentercriticalsection (& CS)
-- Initializecriticalsection (& CS );
-- Deletecriticalsection (& CS );
-- Initializecriticalsectionandspincount
-- Setcriticalsectionspincount
Monitor. Pulse --
Monitor. Wait --

As you can see, monitor simplifies the use of key segments and provides additional wait and pulse methods (because they are not commonly used, they are not expanded here ). However, if the monitor is actually a key segment implementation, the monitor cannot set the number of attempts to rotate the lock. This is a defect.

As for wait and pulse, I personally think it is an alternative to conditional variables. For more information about the condition variables, see [windows] thread-based slim read/write locks.

I once again stressed that the comparison here is just my wishful thinking. It may not be said that monitor is really a key segment!

Note the following issues for lockobj locked by monitor:

    • Lockobj cannot be a value type, because it will be boxed here, and the reference of each packing is different. Therefore, C # ensures this restriction during the compilation phase.
    • Lockobj is better not to be a public object, because it may lead to deadlocks, such as the following extreme situation:
Public class Foo {public void bar () {lock (this) {console. writeline ("Class: FOO: Method: bar") ;}} public class myclient {public void test () {Foo F = new Foo (); lock (f) // The F object {threadstart Ts = new threadstart (F. bar); thread t = new thread (TS); T. start (); // The New thread needs to obtain the access permission of F to execute the bar method, but it has been locked by the current thread, and the new thread will block T. join (); // The New thread cannot return, deadlock }}}
    • Lockobj is recommended not to be a string. A deadlock may occur due to the resident of the string:
Public class Foo {public void bar () {lock ("const") // const will reside in {console. writeline ("Class: FOO: Method: bar") ;}} public class myclient {private string lockobj = "const"; Public void test () {Foo F = new Foo (); lock (lockobj) // because lockobj is "const", "const" is resident, so actually, lock is the same object {threadstart Ts = new threadstart (F. bar); thread t = new thread (TS); T. start (); // The New thread needs to obtain the access permission of lockobj to execute the bar method, but it has been locked by the current thread, and the new thread will block T. join (); // The New thread cannot return, deadlock }}}

 

In the above two examples, lock is used instead of monitor. In fact, after the lock is compiled, it is monitor, but the lock cannot use monitor. tryentry:

. Try {... il_0037: Call void [mscorlib] system. threading. monitor: enter (object, bool &)...} // end. tryfinally {... il_0069: Call void [mscorlib] system. threading. monitor: exit (object )...}

 

Finally, a simple LOG method with a buffer queue is designed, requiring thread security, the implementation of C # is given below (in the previous [windows] thread discussion-the key section of thread synchronization uses the Key Section to provide the Implementation of C ++. The code structure here is almost the same, the comment is omitted ):

Public class loginfo {public int level {Get; set;} Public String message {Get; Set ;}} public class log {Private Static list <loginfo> logqueue = new list <loginfo> (); Private Static object _ locklog = new object (); private Static object _ lockqueue = new object (); Public void log (INT level, string message) {If (Monitor. tryenter (_ locklog) {Monitor. enter (_ lockqueue); foreach (var l in logqueue) {loginternal (L. level, L. message);} logqueue. clear (); monitor. exit (_ lockqueue); loginternal (Level, message); monitor. exit (_ locklog);} else {Monitor. enter (_ lockqueue); logqueue. add (New loginfo {level = level, message = message}); monitor. exit (_ lockqueue) ;}} protected virtual void loginternal (INT level, string message) {// real log actions may take a very long time }}

labor fruit, reprinted please indicate the source: http://www.cnblogs.com/P_Chou/archive/2012/07/18/monitor-in-net-thread-sync.html

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.