C # Use the monitor class, lock class, And mutex class to synchronize multi-thread execution

Source: Internet
Author: User

 

In multithreading, to maintain data consistency, you must lock the data or function that accesses the data. This is common in the database, but most of the programs are single-threaded, so no lock
But in multithreading, to maintain data synchronization, the lock must be required. Fortunately, the framework has provided us with three locking mechanisms, namely, the monitor class and lock.
Keyword and mutex class.

The usage of the lock keyword is relatively simple. The usage of the monitor class is similar to that of the lock class. Both of them lock the data or lock the called function. Mutex is mostly used to lock synchronous calls between multiple threads. In short, monitor and lock are mostly used to lock the called end, while mutex is used to lock the called end. For example, the following program: because such programs are within milliseconds, running the following program may have different results on different machines, running on the same machine at different times has different results. My testing environment is vs2005, WindowsXP, cpu3.0, and 1g monery.
There are two threads thread1, thread2, and a testfunc function in the program. testfunc prints the thread name for calling it and the call time (Mm-level ).
The process calls the testfunc function by 30mm and 100mm respectively. The execution time of testfunc is 50mm. The procedure is as follows:
Using system;
Using system. Collections. Generic;
Using system. text;
Using system. Threading;
Namespace monitorlockmutex
{
Class Program
{
# Region variable
Thread thread1 = NULL;
Thread thread2 = NULL;
Mutex = NULL;
# Endregion
Static void main (string [] ARGs)
{
Program P = new program ();
P. runthread ();
Console. Readline ();
}
Public Program ()
{
Mutex = new mutex ();
Thread1 = new thread (New threadstart (thread1func ));
Thread2 = new thread (New threadstart (thread2func ));
}
Public void runthread ()
{
Thread1.start ();
Thread2.start ();
}
Private void thread1func ()
{
For (int count = 0; count <10; count ++)
{
Testfunc ("thread1 have run" + count. tostring () + "times ");
Thread. Sleep (30 );
}
}
Private void thread2func ()
{
For (int count = 0; count <10; count ++)
{
Testfunc ("thread2 have run" + count. tostring () + "times ");
Thread. Sleep (100 );
}
}
Private void testfunc (string Str)
{
Console. writeline ("{0} {1}", STR, system. datetime. Now. millisecond. tostring ());
Thread. Sleep (50 );
}
}
}
The running result is as follows:

 
We can see that if no lock is applied, the two threads read the testfunc function according to their respective time interval + testfunc execution time (50mm. Because the thread is on
Memory needs to be allocated at the beginning, so 0th calls are not accurate, from 1st ~ The execution interval of thread1 is about 80mm, and the execution interval of thread2 is about
150mm.

Modify testfunc as follows:
Private void testfunc (string Str)
{
Lock (this)
{
Console. writeline ("{0} {1}", STR, system. datetime. Now. millisecond. tostring ());
Thread. Sleep (50 );
}
}
Or the same is true with monitor, as shown below:
Private void testfunc (string Str)
{
Monitor. Enter (this );
Console. writeline ("{0} {1}", STR, system. datetime. Now. millisecond. tostring ());
Thread. Sleep (50 );
Monitor. Exit (this );
}
Both enter and exit are static methods in Monitor. The result of running lock is as follows:


Let's analyze the results, also starting from 1st times. The call interval between the same threads is the thread execution time + testfunc call time. The call interval between different threads is
Testfunc call time. For example, the interval between two consecutive calls of thread1 is about 30 + 50 = 80; the interval between two consecutive calls of thread2 is about
100 + 50 = 150mm. The interval between calling thread1 and thread2 is 50mm. Because testfunc is locked, a thread calls
After testfunc is used, when other threads call testfunc at the same time, the later threads are immediately queued for waiting until the thread with access permission releases the resource.

This is the feature of locking the called function, that is, only one thread can call each time, the number of calls with a higher thread priority is more, and the number of calls with a lower thread priority is less. This is the so-called strong proportion.
Next let's take a look at the usage of the mutex class, and the difference with monitor and lock. Modify the Code as follows:
Private void thread1func ()
{
For (int count = 0; count <10; count ++)
{
Mutex. waitone ();
Testfunc ("thread1 have run" + count. tostring () + "times ");
Mutex. releasemutex ();
}
}

Private void thread2func ()
{
For (int count = 0; count <10; count ++)
{
Mutex. waitone ();
Testfunc ("thread2 have run" + count. tostring () + "times ");
Mutex. releasemutex ();
}
}

Private void testfunc (string Str)
{
Console. writeline ("{0} {1}", STR, system. datetime. Now. millisecond. tostring ());
Thread. Sleep (50 );
}

The running result is as follows:

 
It can be seen that mutex can only be called between mutually exclusive threads, but it cannot be called repeatedly in this thread, that is, waitone () in thread1 only applies
Waitone () is mutually exclusive, but thread1 is not affected by this wainone (). It can be called multiple times, but it is called for the same number of times after the call ends.
Releasemutex.

So how can threads be executed in sequence according to the call sequence? In fact, you can use lock and mutex in combination. The code is changed as follows:

Private void thread1func ()
{
For (int count = 0; count <10; count ++)
{
Lock (this)
{
Mutex. waitone ();
Testfunc ("thread1 have run" + count. tostring () + "times ");
Mutex. releasemutex ();
}
}
}

Private void thread2func ()
{
For (int count = 0; count <10; count ++)
{
Lock (this)
{
Mutex. waitone ();
Testfunc ("thread2 have run" + count. tostring () + "times ");
Mutex. releasemutex ()

}

}

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.