C # beginner-classic instance of lock usage in multiple threads,

Source: Internet
Author: User

C # beginner-classic instance of lock usage in multiple threads,

This article Reprinted from: http://www.cnblogs.com/promise-7/articles/2354077.html

 

I. Lock Definition

The lock keyword can be used to ensure that the code block is executed without being interrupted by other threads. It can define a piece of code as a critical section. A mutex section allows only one thread to run at a time, while other threads must wait. This is achieved by obtaining mutex locks for a given object during the code block operation.

In multiple threads, each thread has its own resources, but the code zone is shared, that is, each thread can execute the same function. This may cause several threads to execute a function at the same time, resulting in data confusion and unexpected results. Therefore, we must avoid this situation.

While in. NET, it is best to understand the process, application domain and thread concepts, Because Lock is for the Thread level, and in. is the application domain in NET isolated from Lock? I guess that threads in different application domains cannot be interrupted through Lock; in addition, it is best to understand the concepts of data segments, code segments, stacks, and stacks.

The C # lock keyword is defined as follows:

Lock (expression) statement_block, where expression represents the object you want to trace, usually the object reference.

If you want to protect an instance of a class, generally you can use this; if you want to protect a static variable (such as a mutex code segment inside a static method ), generally, you can use a class name.

The statement_block is the code of the mutex, which can be executed by only one thread at a time.

Ii. briefly explain the execution process

Let's take a look at the execution process. The sample code is as follows:

Private static object ojb = new object ();

Lock (obj)

{

// Lock the Running code segment

} Suppose thread A is executed first, and thread B is A little slower. Thread A executes the lock statement to determine whether the obj has applied for A mutex lock. It is determined that the object is implemented one by one with an existing lock. referenceEquals comparison (not confirmed here). If it does not exist, apply for A new mutex lock. Then thread A enters the lock.

In this case, it is assumed that thread B is started, and thread A has not executed the code in the lock. Thread B executes the lock statement and checks that obj has applied for A mutex lock, so it waits until thread A finishes executing the lock and releases the mutex lock, thread B can apply for a new mutex lock and execute the code in the lock.

Iii. Selection of Lock objects

Next, let's talk about the lock object.

1. Why cannot I lock the value type?

For example, what about lock (1? Lock is essentially the Monitor. Enter, and Monitor. Enter will bind the value type. Each lock is the boxed object. The lock is similar to the syntax sugar of the compiler. Therefore, the compiler directly limits the lock value type. Even if the compiler allows you to lock (1), but the object. referenceEquals () always returns false (because it is a different object after each packing), that is, each time it is determined that no mutex lock is applied, so that at the same time, other threads can still access the code in it and cannot achieve the synchronization effect. Similarly, lock (object) 1) does not work.

2. Lock string

What about the lock ("xxx") string? The original words on MSDN are:

Locking a string is especially dangerous because the string is "Temporarily" by the Common Language Runtime Library (CLR ". This means that there is only one instance for any given string in the entire program, and the same object represents the text in all threads in all running application domains. Therefore, as long as a lock is placed on a string with the same content anywhere in the application process, all instances of the string in the application will be locked.

3. Lock objects recommended by MSDN

Generally, it is better to avoid locking the public type or locking an object instance that is not controlled by the application. For example, if the instance can be publicly accessed, lock (this) may be faulty because uncontrolled Code may also lock the object. This may cause a deadlock, that is, two or more threads are waiting to release the same object. For the same reason, locking public data types (compared to objects) may also cause problems.

Besides, lock (this) is only valid for the current object. If multiple objects cannot be synchronized.

For custom classes, private read-only static objects are recommended, for example:

Private static readonly object obj = new object ();

Why should I set it to read-only? At this time, if the obj value is changed in the lock code segment, other threads will be unobstructed. Because the mutex lock object has changed, object. ReferenceEquals will inevitably return false.

4. lock (typeof (Class ))

Like locking strings, the range is too wide.

5. Special questions: detailed explanations of Lock (this)

In previous programming, I used lock (this) to solve the lock problem. After a problem occurs, I looked at MSDN and suddenly found the following lines: Generally, we should avoid locking the public type, otherwise, the instance is out of the control scope of the Code. Common structures such as lock (this), lock (typeof (MyType), and lock ("myLock") violate this rule: if an instance can be accessed by the public, C # lock this problem will occur. If MyType can be accessed by the public, the lock (typeof (MyType) problem will occur. Any other code that uses the same string in the process will share the same lock, so the lock ("myLock") problem occurs.

Let's take a look at the issue of C # lock this: if there is a class Class1, this class has a method to implement mutual exclusion using lock (this:

In the same Class1 instance, The Method2 can be mutually exclusive. However, if two Class1 instances run Method2 respectively, there is no mutex effect. Because the lock here only locks the current instance object.

Lock (typeof (MyType) locks a wider range of objects, because all instances of a class have only one type object (this object is the return result of typeof), Lock it, it locks all instances of this object. Microsoft recommends that you do not use lock (typeof (MyType) because locking a type object is a very slow process, other threads in the class, or even other programs running in the same application domain, can access this type of object. Therefore, they may be used to lock the type object instead of you, it completely blocks your execution and causes your own code to be suspended.

Locking a string is even more amazing. As long as the string content is the same, it can cause the program to be suspended. The reason is that in. NET, the string will be temporarily stored. If the two variables have the same string content,. NET will allocate the temporary String object to the variable. So if both of them are using lock ("my lock"), they actually lock the same object. At this point, Microsoft provides a recommended lock usage: locking a private static member variable.

. NET in some collection classes (such as ArrayList, HashTable, Queue, Stack) has provided a lock Object SyncRoot, and used the Reflector tool to view the SyncRoot attribute code. In the Array, this attribute has only one sentence: return this, which is the same as the current instance of lock array. SyncRoot in ArrayList is different.

The Interlocked class provides atomic operations for variables shared by multiple threads (use this class if the object you want to lock is of the basic data type ), the CompareExchange method compares the current syncRoot with null. If they are equal, replace them with the new object () method to ensure thread security when multiple threads use syncRoot. Another method in the Collection class is related to synchronization: Synchronized. This method returns a wrapper class of the corresponding collection class, which is thread-safe, because most of his methods use lock for synchronization, such as the Add method:

It is important to note that enumeration of a set from start to end is not a thread-safe process. Even if a set has been synchronized, other threads can modify the set, which causes an exception in the number of enumerations. To ensure thread security during enumeration, you can lock the set throughout the enumeration process:

Last

Note: Do not lock the public type; otherwise, the instance will be out of the control scope of the Code. Common structures such as lock (this), lock (typeof (MyType), and lock ("myLock") violate this rule: 1) if an instance can be accessed by the public, the lock (this) problem will occur; 2) If MyType can be accessed by the public, the lock (typeof (MyType) problem will occur; 3) any other code that uses the same string in the process will share the same lock, so the lock ("myLock") problem occurs. The best practice is to define a private object to lock, or private static object variable to protect the data shared by all instances.

Vi. References

Because the reference materials are saved locally, you can only list the titles and cannot provide the original address. Sorry!

1) Description of the Lock keyword in C # Multithreading

2) Solve the Problem of C # lock this

3) Summary based on the lock keyword in C #

4) C # lock keyword

Link: http://www.soaspx.com/dotnet/csharp/csharp_20120104_8511.html

 


There are a lot of online statements about lock, but there are still a lot of instances about actual usage, but there are many but not refined, not very thorough, however, this example is a good example of using the lock keyword in multiple threads. I am so depressed that I have not found any decent articles on the Internet. Copy them !! If you do not specify the URL, you must be original! I cannot find any examples. I suggest you do it yourself ~

The theory of the lock keyword is introduced below:

One advantage of using multiple threads in an application is that each thread can be executed asynchronously. For Windows applications, time-consuming tasks can be executed in the background, so that the application Windows and controls remain responsive. For server applications, multithreading allows different threads to process each incoming request. Otherwise, each new request cannot be processed until the previous request is fully satisfied. However, the asynchronous nature of threads means that access to resources (such as file handles, network connections, and memory) must be coordinated. Otherwise, two or more threads may access the same resource at the same time, and each thread does not know the operations of other threads. Unexpected data corruption occurs. For simple operations on integer data types, you can use Interlocked class members to implement thread synchronization. For all other data types and non-thread-Safe Resources, only the structure in this topic can be used to safely perform multi-thread processing.

The lock keyword can be used to ensure that the code block is executed without being interrupted by other threads. This is achieved by obtaining mutex locks for a given object during the code block operation.

The parameter provided to the lock keyword must be an object of the reference type, which is used to define the lock range. In the above example, the lock range is limited to this function because no reference to this object exists outside the function. If such a reference exists, the lock range is extended to this object. Strictly speaking, the object provided to lock is only used to uniquely identify resources shared by multiple threads, so it can be any class instance. However, in fact, this object usually indicates the resources that require thread synchronization. For example, if a container object is used by multiple threads, the container can be passed to lock, and the synchronization code block after lock will access the container. As long as other threads lock the container before accessing the container, access to the object will be synchronized securely.

Generally, it is better to avoid locking the public type or locking an object instance that is not controlled by the application. For example, if the instance can be publicly accessed, lock (this) may be faulty because uncontrolled Code may also lock the object. This may cause a deadlock, that is, two or more threads are waiting to release the same object. For the same reason, locking public data types (compared to objects) may also cause problems. Locking a string is especially dangerous because the string is "Temporarily" by the Common Language Runtime Library (CLR ". This means that there is only one instance for any given string in the entire program, and the same object represents the text in all threads in all running application domains. Therefore, as long as a lock is placed on a string with the same content anywhere in the application process, all instances of the string in the application will be locked. Therefore, it is best to lock private or protected members that are not temporarily retained. Some classes provide members dedicated for locking. For example, the Array type provides SyncRoot. Many Collection types also provide SyncRoot.

There are annotations below, and some thread basics are understandable. [VS2008. NET3.5]

 

/*
This instance is a classic instance of lock usage in a thread, so that the resulting balance will not be negative
At the same time, ten threads are initialized and ten are started. However, due to locking, only a few of the following methods can be enabled to call the WithDraw method.
By http://hi.baidu.com/jiang_yy_jiang
*/
Using System;

Namespace ThreadTest29
{
Class Account
{
Private Object thisLock = new object ();
Int balance;
Random r = new Random ();

Public Account (int initial)
{
Balance = initial;
}

Int WithDraw (int amount)
{
If (balance <0)
{
Throw new Exception ("negative Balance .");
}
// Ensure that only one thread uses resources, one enters the critical state, and the other uses the object mutex lock. 10 started threads cannot execute this method all.
Lock (thisLock)
{
If (balance> = amount)
{
Console. WriteLine ("--------------------------:" + System. Threading. Thread. CurrentThread. Name + "---------------");

Console. WriteLine ("Balance before Withdrawal is called:" + balance );
Console. WriteLine ("input Amount Withdrawal:-" + amount );
// If no object mutex lock is added, the following subtraction may be executed in 10 threads. The time segment consumed by addition and subtraction is very small. Multiple Threads may be executed simultaneously, resulting in a negative number.
Balance = balance-amount;
Console. WriteLine ("Balance after Withdrawal is called:" + balance );
Return amount;
}
Else
{
// Final result
Return 0;
}
}
}
Public void DoTransactions ()
{
For (int I = 0; I <100; I ++)
{
// Generate a random number for the balance subtrahend
WithDraw (r. Next (1,100 ));
}
}
}

Class Test
{
Static void Main (string [] args)
{
// Initialize 10 threads
System. Threading. Thread [] threads = new System. Threading. Thread [10];
// Set the balance initialization to 1000
Account acc = new Account (1000 );
For (int I = 0; I <10; I ++)
{
System. Threading. Thread t = new System. Threading. Thread (new System. Threading. ThreadStart (acc. DoTransactions ));
Threads [I] = t;
Threads [I]. Name = "Thread" + I. ToString ();
}
For (int I = 0; I <10; I ++)
{
Threads [I]. Start ();
}
Console. ReadKey ();
}
}
}

The effect is as follows:

 

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.