The problem of using monitor or mutex for synchronization control: Because the exclusive access model does not allow any form of concurrent access, this efficiency is always not very high. In many cases, applications perform read operations when accessing resources, with fewer write operations. To solve this problem, C # provides the system. Threading. readerwriterlock class to adapt to Multi-User Read/single-user write scenarios. This class can implement the following functions: If the resource is not locked by the write operation, any thread can lock the resource for read operations, and there is no limit on the number of read operation locks, that is, multiple threads can lock the read operation on the resource at the same time to read data. If the resource has not been added with any read or write operation locks, one and only one thread can add write operation locks to the resource to write data. In short, the read operation lock is a shared lock that allows multiple threads to read data at the same time. The write operation lock is an exclusive lock that allows only one thread to perform write operations at the same time.
The sample code is as follows:
Using system;
Using system. Threading;
Namespace processtest
{
Class Program
{
// Resource
Static int theresource = 0;
// Read and write operation locks
Static readerwriterlock RWL = new readerwriterlock ();
Static void main (string [] ARGs)
{
// Create two read operation threads and two write operation threads respectively, and start
Thread tr0 = new thread (New threadstart (read ));
Thread tr1 = new thread (New threadstart (read ));
Thread tr2 = new thread (New threadstart (write ));
Thread TR3 = new thread (New threadstart (write ));
Tr0.start ();
Tr1.start ();
Tr2.start ();
Tr3.start ();
// Wait until the thread execution is complete
Tr0.join ();
Tr1.join ();
Tr2.join ();
Tr3.join ();
System. Console. readkey ();
}
// Read data
Static void read ()
{
For (INT I = 0; I <3; I ++)
{
Try
{
// Apply for the read operation lock. If the read operation lock is not obtained within ms, discard
RWL. acquirereaderlock (1000 );
Console. writeline ("start to read data, theresource = {0}", theresource );
Thread. Sleep (10 );
Console. writeline ("Data Reading ends, theresource = {0}", theresource );
// Release the read operation lock
RWL. releasereaderlock ();
}
Catch (applicationexception)
{
// Handling of failed read operation locks
}
}
}
// Write data
Static void write ()
{
For (INT I = 0; I <3; I ++)
{
Try
{
// Apply for a write operation lock. If the lock is not obtained within ms, discard it.
RWL. acquirewriterlock (1000 );
Console. writeline ("start to write data, theresource = {0}", theresource );
// Add theresource to 1
Theresource ++;
Thread. Sleep (100 );
Console. writeline ("Data Writing ends, theresource = {0}", theresource );
// Release the write operation lock
RWL. releasewriterlock ();
}
Catch (applicationexception)
{
// An error occurred while obtaining the write operation lock.
}
}
}
}
}
In the preceding example, two read threads and two write threads are created respectively for reading and writing. The running result is as follows:
Observe the running results. We can easily see that the read operation lock is a shared lock that allows multiple threads to read data at the same time. The write operation lock is an exclusive lock that allows only one thread to perform write operations.
If a thread wants to increase the lock level and change it to a write operation lock after obtaining the read operation lock, it can call the upgradetowriterlock (INT timeout) method of the readerwriterlock class, this method returns a lockcookie value that saves the status of the thread lock before the upgradetowriterlock method is called. After the write operation is complete, you can call the downgradefromwriterlock (lockcookie) method. This method restores the thread lock to the status before the upgradetowriterlock method is called Based on the passed lockcookie parameter value. For more information, see msdn.