C # Multithreading concurrency Lock Mode-Summary

Source: Internet
Author: User
Tags mutex

Opening:

Mutex or lock Monitor mutex mode!

Muex Monitor Lock Autoeventset Manualeventset

The subsequent

ReaderWriterLock
ReaderWriterLockSlim class

Represents the lock state used to manage resource access, enabling multithreaded reads or exclusive write access.

readerwriterlockslim to protect a resource it is read by multiple threads and written to by one thread at A time. " > use  readerwriterlockslim  to protect resources that are read by multiple threads but written only by one thread at a time.  readerwriterlockslim allows multiple threads to is in read mode, allows one thread to is in write mode with Exclusive ownership of the lock, and allows one thread that have read access to is in upgradeable read mode, from which th E thread can upgrade to write mode without have to relinquish it read access to the resource. " >readerwriterlockslim  allows multiple threads to be in read mode, allowing one thread to be in write mode and exclusive lock state, while also allowing a thread with Read permission to be in upgradeable read mode , the thread in this mode can be upgraded to write mode without discarding read permission to the resource.

Note ReaderWriterLockSlim is similar to ReaderWriterLock, and simply simplifies the rules for recursion, escalation, and downgrade lock states. ReaderWriterLockSlim can avoid a variety of potential deadlock situations. In addition, ReaderWriterLockSlim performance is significantly better than ReaderWriterLock. It is recommended to use ReaderWriterLockSlim in all new development work.

The above references are from MSDN

C # Threading Manual Chapter III using the threading ReaderWriterLock class

2012-02-07 21:53 by Danielwise, 4166 reading, 1 reviews, favorites, compilation

A ReaderWriterLock class defines a lock that implements single-write read-only semantics. This class is typically used when a file operation can be read by multiple threads but can be written only by one thread. The following are the four main methods in the ReaderWriterLock class:

A. AcquireReaderLock (): This overloaded method acquires a reader lock that accepts a timeout value of an integer or TimeSpan type. Timeout is a powerful tool to detect deadlocks.

B. AcquireWriterLock (): This overloaded method acquires a writer lock that accepts a timeout value of an integer or TimeSpan type.

C. Releasereaderlock (): Release reader lock.

D. Releasewriterlock (): Releases the writer lock.

Use the ReaderWriterLock class to enable multithreading to safely read data concurrently. The data is locked only when the thread is updating. The reader thread can then acquire the lock without the writer having the lock. The writer thread can no longer acquire a lock when the reader thread or the writer thread has a lock.

The following list, ReadeWriteLock.cs, describes how to use the ReaderWriterLock () Lock:

/*************************************/* Copyright (c) Daniel Dong * * Author:daniel Dong * blog:www.cnblogs.com/d anielwise * Email: [email protected] * */using system;using system.collections.generic;using System.Text;using        System.threading;namespace readwritelock{public class ReadWrite {private ReaderWriterLock rwl;        private int x;        private int y;        Public ReadWrite () {rwl = new ReaderWriterLock (); } public void readints (ref int A, ref int b) {rwl.            AcquireReaderLock (Timeout.infinite);                try {a = this.x;            b = this.y; } finally {rwl.            Releasereaderlock (); }} public void writeints (int a, int b) {rwl.            AcquireWriterLock (Timeout.infinite);                try {this.x = A;                This.y = b; Console.WriteLine ("X= "+ this.x +" y = "+ this.y +" ThreadID = "+ Thread.CurrentThread.GetHashCode (            )); } finally {rwl.            Releasewriterlock ();        }}} public class Rwapp {private ReadWrite RW = new ReadWrite ();            public static void Main (string[] args) {Rwapp e = new Rwapp ();            Writer Threads Thread wt1 = new Thread (new ThreadStart (E.write)); Wt1.            Start ();            Thread wt2 = new Thread (new ThreadStart (E.write)); Wt2.            Start ();            Reader Threads Thread rt1 = new Thread (new ThreadStart (E.read)); Rt1.            Start ();            Thread rt2 = new Thread (new ThreadStart (E.read)); Rt2.            Start ();        Console.ReadLine ();            } private void Write () {int a = 10;            int b = 11;           Console.WriteLine ("************** Write *************"); for (int i = 0; i < 5; i++) {this.rw.WriteInts (a++, b++);            Thread.Sleep (1000);            }} private void Read () {int a = 10;            int b = 11;            Console.WriteLine ("************** Read *************");                for (int i = 0; i < 5; i++) {this.rw.ReadInts (ref a, ref B); Console.WriteLine ("For i =" + i + "a =" + A + "b =" + B + "                Theadid = "+ Thread.CurrentThread.GetHashCode ());            Thread.Sleep (1000); }        }    }}

The output of the Readwritelock may be similar to the following table:

In the list above, threads Wt1 and Wt2 are the writer threads that get write locks in the Writeints () method, thread Rt1 and RT2 are reader threads that get reader locks in the Readints () method. In the Writeints () method, the values of the variable x and y are changed to A and B, respectively. When a thread wt1 or WT2 obtains a writer lock by calling the AcquireWriterLock () method, then until the thread calls Releasewriterlock () Any other threads, including reader threads Rt1 and rt2, are not allowed to access the corresponding object before the method releases the lock. This behavior is similar to monitors. In the Readints () method, thread Rt1 and Rt2 obtain a reader lock by calling the AcquireReaderLock () method, which can be accessed concurrently by the two threads. until the reader thread releases their reader lock, the writer thread (WT1 and WT2) To be allowed access to the corresponding object. Only reader threads can be accessed concurrently after they have been acquired by the reader lock.

The monitors class is too "safe" for just wanting to read data rather than write data. Monitors also has some performance issues, and performance bottlenecks can be avoided for read-only types of access. The ReaderWriterLock class provides a perfect solution to data read-write problems by allowing any number of threads to read data concurrently. Locks the data when the thread updates the data. The writer thread can obtain a lock when there is no writer thread that owns the lock. A writer lock can acquire a lock without a reader thread or a writer thread owning a lock. As a result, ReaderWriterLock is like a key part of the code, it also supports a timeout value, which is useful when detecting deadlocks.

1. Differences in several synchronization methods

Lock and Monitor are. NET implemented with a special structure, monitor objects are fully managed, fully portable, and may be more efficient in terms of operating system resource requirements, synchronization is faster, but cannot be synchronized across processes. Lock (Monitor.Enter and Monitor.Exit method encapsulation), the main role is to lock the critical section, so that the critical section code can only be executed by the thread that gets the lock. Monitor.Wait and monitor.pulse are used for thread synchronization, similar to signal manipulation, personal feeling is more complex, easy to cause deadlocks.

Mutex mutexes and Event objects Eventwaithandler belong to kernel objects, thread synchronization with kernel objects, threads must be switched between user mode and kernel mode, so generally inefficient, but with kernel objects such as mutex objects and event objects, You can synchronize between threads in multiple processes.

Mutex mutex similar to a baton, the thread to get the baton can start to run, of course, the baton only belongs to one thread at a time (thread Affinity), if the thread does not release the baton (Mutex.releasemutex), then no way, All other threads that need to run the baton know that they can wait to see the excitement.

The EventWaitHandle class allows threads to communicate with each other by signaling. Typically, one or more threads are blocked on EventWaitHandle until an unblocked thread calls the Set method to free one or more blocked threads.

2. When to lock

The first thing to understand is that the lock is to solve the competitive condition, that is, multiple threads accessing a resource at the same time, causing unexpected results. For example, in the simplest case, a counter, with two threads plus one, results in a loss of a count, but a fairly frequent lock can result in a performance drain and the most terrifying case of deadlock. So under what circumstances do we need to use locks, and under what circumstances do we not need them?

1) Only shared resources need to be locked
Only shared resources that can be accessed by multithreading need to consider locks, such as static variables, such as values in some caches, and variables that are inside the thread do not need to be locked.

2) Use lock more, less mutex
If you must use a lock, try not to use the locking mechanism of the kernel module, for example. NET Mutex,semaphore,autoresetevent and Manuresetevent, the use of such mechanisms involves the system in user mode and kernel mode switching between the performance is much worse, but their advantage is that the thread can be synchronized across processes, so should be clear Chu's understanding of their differences and scope of application.

3) know how your program works
In fact, most of the logic in web development is carried out in a single thread, and a request is processed in a separate thread, where most of the variables belong to this thread, and there is no need to consider locking at all. Of course, for the data in the Application object in ASP, we need to consider locking.

4) give the lock to the database
In addition to storing data in the database, there is an important use of synchronization, the database itself with a complex set of mechanisms to ensure the reliability and consistency of data, which saves us a lot of effort. To ensure synchronization at the source of the data, most of our energy can be focused on the synchronization of other resources such as cache access. In general, we consider locking only when multiple threads are involved in modifying the same record in the database.

5) Business logic requirements for transactional and thread safety
This is the most fundamental thing, the development of a fully thread-safe program is a very time-consuming thing, in the case of electronic commerce and other financial systems, many of the logic must be strict thread safety, so we have to sacrifice some performance, and a lot of development time to do this work. And in general applications, in many cases, although the program has the risk of competition, we can still not use locks, for example, sometimes the counter less than one, the result is harmless, we can not have to control it.

3.InterLocked class

The Interlocked class provides methods for synchronizing access to variables shared by multiple threads. If the variable is in shared memory, the mechanism can be used by threads of different processes. Interlocked operations are atomic, meaning that the entire operation is a unit that cannot be interrupted by another interlocked operation on the same variable. This is important in preemptive multithreaded operating systems in which a thread can be suspended after loading a value from a memory address but before it has the opportunity to change and store the value.

Let's take a look at an example of a interlock.increment () that increments the specified variable and stores the result in an atomic form, as shown in the following example:


Class Interlockedtest
{
public static Int64 i = 0;

public static void Add ()
{
for (int i = 0; i < 100000000; i++)
{
Interlocked.Increment (ref interlockedtest.i);
INTERLOCKEDTEST.I = interlockedtest.i + 1;
}
}


public static void Main (string[] args)
{
thread T1 = new Thread (new ThreadStart (Interlockedtest.add));
Thread t2 = new Thread (new ThreadStart (Interlockedtest.add));

T1. Start ();
T2. Start ();

T1. Join ();
T2. Join ();

Console.WriteLine (Interlockedtest.i.tostring ());
Console.read ();
}
}

Output 200000000, if the Interlockedtest.add () method replaces the Interlocked.Increment () method with commented-out statements, the results will be unpredictable, with different results per execution. The Interlockedtest.add () method guarantees the atomicity of the plus 1 operation, which is functionally equivalent to the lock lock used for the automatic add operation. At the same time we also notice that the Interlockedtest.add () time is more than the direct use of + number plus 1 will take much longer, so that the lock resource loss is still very obvious.

In addition, there are several common methods for the Interlockedtest class, which can be consulted on MSDN.

4. Synchronization of collection classes

. NET in some collection classes, such as queue, ArrayList, Hashtable, and Stack, has provided an object SyncRoot for lock use. Using reflector to see the SyncRoot attribute (stack.synchroot slightly different) source code is as follows:


Public virtual object syncroot
{
     get
    {
        if  (this._ Syncroot == null)
        {
             //if _syncroot and null are equal, assign New object to _syncroot
  The            //interlocked.compareexchange method guarantees that multiple threads are using the SyncRoot is thread-safe
             Interlocked.compareexchange (Ref this._syncroot, new object (),  null);
        }
        return this._syncRoot;
    }
}

It is important to note that MSDN mentions that enumerating a collection from beginning to end is not inherently a thread-safe process. Even if a collection is synchronized, other threads can still modify the collection, which causes the enumerator to throw an exception. To ensure thread safety during enumeration, you can lock the collection during the entire enumeration, or catch exceptions that are thrown because of changes made by other threads. The following code should be used:

Queue Use lock example

It is also important to note that the collection class provides a synchronous-related method, synchronized, that returns the wrapper class of the corresponding collection class, which is thread-safe because most of his methods are synchronized with the lock keyword. As Hashtable's synchronized returns a new thread-safe hashtable instance, the code is as follows:


In a multithreaded environment, as long as we instantiate the Hashtable in the following way
Hashtable HT = hashtable.synchronized (new Hashtable ());

The following code is implemented in the. NET Framework Class Library to increase awareness of synchronized
[HostProtection (SecurityAction.LinkDemand, Synchronization=true)]
public static Hashtable Synchronized (Hashtable table)
{
if (table = = null)
{
throw new ArgumentNullException ("table");
}
return new synchashtable (table);
}


Synchashtable Several common methods, we can see that the internal implementation has added the LOCK keyword to ensure thread safety
public override void Add (object key, Object value)
{
Lock (this._table. SyncRoot)
{
This._table. ADD (key, value);
}
}

public override void Clear ()
{
Lock (this._table. SyncRoot)
{
This._table. Clear ();
}
}

public override void Remove (object key)
{
Lock (this._table. SyncRoot)
{
This._table. Remove (key);
}
}

Thread synchronization is a very complex topic, and it is just a matter of summarizing the relevant knowledge according to a project of the company. What are the usage scenarios for these synchronization methods? What are the subtle differences? Further study and practice is still pending.

C # Multithreading concurrency Lock Mode-Summary

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.