. Net Object-Oriented multi-thread (Multithreading) and multi-thread advanced applications,. netmultithreading
In the. net Object-Oriented programming stage, thread security and thread conflict solutions in thread resource sharing; multi-thread synchronization uses thread locks and thread notifications for thread synchronization. The details are as follows:
1. ThreadStatic features
Features: [ThreadStatic]
Function: specify that static fields have different values in different threads.
Before that, let's take a look at a multi-threaded example:
We define a static field:
Static int num = 0;
Then create two threads to accumulate them separately:
New Thread () => {for (int I = 0; I <1000000; I ++) ++ num; Console. writeLine ("from {0 }:{ 1}", Thread. currentThread. name, num) ;}{ Name = "thread 1 "}. start (); new Thread () => {for (int I = 0; I <2000000; I ++) ++ num; Console. writeLine ("from {0 }:{ 1}", Thread. currentThread. name, num) ;}{ Name = "thread 2 "}. start ();
The running results are as follows:
As you can see, the three running results are different. This problem is caused by synchronization and sharing in multiple threads, that is, multiple threads share a single resource at the same time. The simplest way to solve the above problem is to use the ThreadStatic feature of static fields.
When defining static fields, add the [ThreadStatic] feature as follows:
Copy codeThe Code is as follows:
[ThreadStatic]
Static int num = 0;
The result is as follows:
The results are the same no matter how many times it is run. When a field is modified by the ThreadStatic feature, its values are different in each thread, that is, each thread will re-allocate the memory space for the static field, of course, it is a new operation. In this way, the problems caused by the static field will disappear.
2. Resource Sharing
Multi-threaded resource sharing, that is, multi-threaded synchronization (that is, resource synchronization). Note that thread synchronization refers to the synchronization of resources accessed by the thread, not the synchronization of the thread itself.
In the process of using multithreading, not all threads access different resources.
Let's take a look at a thread example. If we don't know how long the thread will take to complete, we will wait for a fixed period of time (for example, 500 ms ):
First define a static field:
Static int result;
Creation thread:
Thread myThread = new Thread(() =>{ Thread.Sleep(1000); result = 100;});myThread.Start();Thread.Sleep(500); Console.WriteLine(result);
The running result is as follows:
We can see that the result is 0, which is obviously not what we want, but often in the thread execution process, we do not know how long it will take to complete, can there be a notification after the thread completes?
There are many stupid methods here. For example, we may think of using a loop to check the thread status, which is not ideal.
. NET provides us with a Join method, that is, thread blocking, which can solve the above problem. We use Stopwatch to remember the time,
The code for improving the thread is as follows:
System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew();Thread myThread = new Thread(() =>{ Thread.Sleep(1000); result = 100;});myThread.Start();Thread.Sleep(500);myThread.Join();Console.WriteLine(watch.ElapsedMilliseconds);Console.WriteLine(result);
The running result is as follows:
The results are consistent with what we want.
3. thread lock
In addition to the method in the above example, for thread synchronization,. NET also provides a locking mechanism for us to solve synchronization. The above example is improved again:
First define a static field to store the lock:
Static object locker = new object ();
Here, we do not need to consider what this object is. Continue to look at the improved thread:
System. diagnostics. stopwatch watch = System. diagnostics. stopwatch. startNew (); Thread t1 = new Thread () => {lock (locker) {Thread. sleep (1000); result = 100 ;}}); t1.Start (); Thread. sleep (100); lock (locker) {Console. writeLine ("thread time consumption:" + watch. elapsedMilliseconds); Console. writeLine ("thread output:" + result );}
The running result is as follows:
The running result is the same as that in the preceding example. If the thread processing process is complicated, the time consumption is obviously reduced. This is a more efficient way to complete thread synchronization than blocking.
4. Thread notification
As mentioned above, can we notify the waiting thread after a thread is completed? Here. NET provides us with an event notification method to solve this problem.
4.1 AutoResetEvent
Define a notification object first
Copy codeThe Code is as follows:
Static EventWaitHandle tellMe = new AutoResetEvent (false );
Improve the above thread as follows:
System. diagnostics. stopwatch watch = System. diagnostics. stopwatch. startNew (); Thread myThread = new Thread () => {Thread. sleep (1000); result = 100; tellMe. set () ;}); myThread. start (); tellMe. waitOne (); Console. writeLine ("thread time consumption:" + watch. elapsedMilliseconds); Console. writeLine ("thread output:" + result );
The running result is as follows:
4.2 ManualResetEvent
There is also a ManualResetEvent manual mode relative to AutoResetEvent. The difference is that ManualResetEvent is still passable after the thread ends, unless manual Reset is disabled. The following is an example:
First define a manual notification object:
static EventWaitHandle mre = new ManualResetEvent(false);
Creation thread:
System. diagnostics. stopwatch watch = System. diagnostics. stopwatch. startNew (); Thread myThreadFirst = new Thread () => {Thread. sleep (1000); result = 100; mre. set () ;}) {Name = "Thread 1"}; Thread myThreadSecond = new Thread () =>{ mre. waitOne (); Console. writeLine (Thread. currentThread. name + "get result:" + result + "(" + System. dateTime. now. toString () + ")") ;}{ Name = "thread 2"}; myThreadFirst. start (); myThreadSecond. start (); mre. waitOne (); Console. writeLine ("thread time consumption:" + watch. elapsedMilliseconds + "(" + System. dateTime. now. toString () + ")"); Console. writeLine ("thread output:" + result + "(" + System. dateTime. now. toString () + ")");
The running result is as follows:
4.3. Semaphore
Semaphore is also a kind of thread notification. In the above notification mode, if the Reset () is disabled when many threads are enabled, if Sleep is not used for Sleep, it is very likely that a thread will be shut down in advance when some threads are not recovered. This is difficult to predict ,. NET provides a more advanced notification method Semaphore, which ensures that the above problems will not occur in the case of super-threading.
First, define a static field of the notification object:
Copy codeThe Code is as follows:
Static Semaphore sem = new Semaphore (2, 2 );
Create 100 threads in a loop:
For (int I = 1; I <= 100; I ++) {new Thread () => {sem. waitOne (); Thread. sleep (30); Console. writeLine (Thread. currentThread. name + "" + DateTime. now. toString (); sem. release () ;}) {Name = "Thread" + I }. start ();}
The running result is as follows:
We can see the complete output of what we want to see.
5. Highlights of this section:
A. ThreadStatic feature of the static field in the thread. This field has different values in different threads.
B. Several Ways of thread synchronization, thread lock and thread notification
C. Two Methods of thread notification: AutoResetEvent/ManualResetEvent and Semaphore
So far, the introduction of. net Object-Oriented multi-thread (Multithreading) and multi-thread advanced applications has reached this point.