This is a new topic for old bottles. I just want to practice and organize what I have seen today for future use. At the same time, I hope it will help you.
A starting from the singleton Mode
CodeAs follows:
ClassProgram
{
Static voidMain (String[] ARGs)
{
SingletonDemo1 =Singleton. INIT ();
SingletonDemo2 =Singleton. INIT ();
}
}
Public classSingleton
{
PrivateSingleton (){}
Private StaticSingletonInstance =Null;
Private Static readonly objectSingleobj =New Object();
Public staticSingletonInit ()
{
If(Null= Instance)
{
Lock(Singleobj)// Singleobj cannot be replaced by instance
{
If(Null= Instance)
{
Instance =NewSingleton();
}
}
}
ReturnInstance;
}
}
About Singleton mode, you can refer to: http://terrylee.cnblogs.com/archive/2005/12/09/293509.html
B. Lock Method
In the code of the preceding single-column mode:
If:Private Static readonly objectSingleobj =New Object();
To:Private Static readonly objectSingleobj =Null;
An unhandled exception will be thrown at the lock () method: system. argumentnullexception: The value cannot be blank!
● LockKeywordStatement BlockMarkCritical Section;
●The OBJ object in the lock (OBJ) method is:Obtains the specified exclusive lock object..
If the OBJ object is null, argumentnullexception is abnormal.
●The lock method is compiled into monitor. Enter () and monitor. Exit () in msil (). For example:
Public static voidMylock ()
{
Lock(Typeof(Program ))
{
}
}
The above Code uses the lock statement to synchronize mylock. After this method is compiled into msil, the code is shown in:
From the labeled area, we can see that a lock statement is compiled into the enter and exit methods of monitor.
The lock function is equivalent to directly calling the entry method of monitor, and automatically calling the exit method of monitor to unlock the lock upon completion.
C. About the monitor class
●The monitor class belongs to the system. Threading namespace;
●The monitor class provides a synchronous access mechanism to objects;
●Use monitor to lock the object (that is, the reference type) instead of the value type;
●The monitor type is safe for multi-threaded operations;
Example 1 of the monitor class:
ClassProgram2
{
Static voidMain (String[] ARGs)
{
Mymonitor1Mon_1 =NewMymonitor1();
Mon_1.test ();
}
}
ClassMymonitor1
{
Private objectOBJ =New Object();
Public voidTest ()
{
// Start locking
System. threading.Monitor. Enter (OBJ );
Try
{
// Lock Region
}
Catch(ExceptionE)
{
// Exception Handling Code
}
Finally
{
// Unlock
System. threading.Monitor. Exit (OBJ );
}
}
}
Example 2 of the monitor class:
ClassProgram3
{
Static voidMain (String[] ARGs)
{
// Multiple threads call the test method
ThreadT1 =NewThread(Mymonitor2. Test );
ThreadT2 =NewThread(Mymonitor2. Test );
T1.start ();
T2.start ();
}
}
ClassMymonitor2
{
Private Static objectOBJ =New Object();
Public static voidTest ()
{
// Use the tryentry method to set a lock timeout
If(Monitor. Tryenter (OBJ, 2000 ))
{
Try
{
Console. Writeline ("Wait 4 seconds to start");
Thread. Sleep (4000 );
Console. Writeline ("Wait for 4 seconds to end");
}
Finally
{
// Unlock
Monitor. Exit (OBJ );
}
}
Else
{
Console. Writeline ("It has timed out for 2 seconds! ");
}
}
}
D. About synchronization and mutex
You can use the monitor class to solve the synchronization problem.
When using the monitor class, we recommend that you replace the monitor. Enter () method with the monitor. tryenter () method.
UseMonitor. Enter () methodThe Code is as follows:
Monitor. Entry (lockobj );
Try
{
// Lockobj synchronization Zone
}
Catch(Exception E)
{
// Exception Handling Code
}
Finally
{
Monitor. Exit (lockobj );// Unlock
}
Note: If you directly go to the C # sourceProgramTo use the monitor class, you must call the exit method to explicitly unlock the lock.
UseMonitor. tryenter () methodThe Code is as follows:
If(Monitor. tryentry (lockobj, 1000 ))
{
Try
{
}
Finally
{
Monitor. Exit (lockobj );
}
}
Else
{
// Processing code after timeout
}
Note: Use the tryentry method to set a lock timeout, in milliseconds.
The above Code sets the lock timeout time to 1 second.
If the lockobj has not been unlocked within one second, the tryentry method returns false;
If lockobj is unlocked within one second, the tryentry method returns true.
In this way, you can use the tryentry method to avoid deadlocks.
Synchronization and mutexExample 1:
ClassProgram4
{
Static voidMain (String[] ARGs)
{
ThreadA =NewThread(Testclass1. Geta );
A. Name ="Thread_a";
ThreadB =NewThread(Testclass1. Getb );
B. Name ="Thread_ B";
A. Start ();
B. Start ();
}
}
ClassTestclass1
{
Private Static objectResource_a =New Object();
Private Static objectResource_ B =New Object();
Public static voidGeta ()
{
Mywrite ("In geta ()");
If(Monitor. Tryenter (resource_a, 2000 ))
{
Mywrite ("Get resource_a");
Getb ();
Thread. Sleep (2000 );
Monitor. Exit (resource_a );
Mywrite ("Exit resource_a");
}
Else
{
Mywrite ("No has resource_a");
}
}
Public static voidGetb ()
{
Mywrite ("In getb ()");
If(Monitor. Tryenter (resource_ B, 1000 ))
{
Mywrite ("Get resource_ B");
Geta ();
Thread. Sleep (1000 );
Monitor. Exit (resource_ B );
Mywrite ("Exit resource_ B");
}
Else
{
Mywrite ("No has resource_ B");
}
}
// Custom printing method
Private Static voidMywrite (StringStr)
{
Console. Writeline (Thread. Currentthread. Name + Str );
}
}
The result is as follows:
Synchronization and mutexExample 2:
ClassProgram5
{
Static voidMain (String[] ARGs)
{
ThreadA =NewThread(Testclass2. Geta );
A. Name ="Thread_a";
ThreadB =NewThread(Testclass2. Getb );
B. Name ="Thread_ B";
A. Start ();
B. Start ();
}
}
ClassTestclass2
{
// Exclusive lock object
Private Static objectResource_a =New Object();
// Exclusive lock object B
Private Static objectResource_ B =New Object();
Public static voidGeta ()
{
Mywrite ("In geta ()");
If(Monitor. Tryenter (resource_a, 1000 ))
{
Mywrite ("Get resource_a");
Thread. Sleep (1000 );
// Getb ();
If(Monitor. Tryenter (resource_ B, 2000 ))
{
Monitor. Exit (resource_ B );
}
Monitor. Exit (resource_a );
Mywrite ("Exit resource_a");
}
Else
{
Mywrite ("No has resource_a");
}
}
Public static voidGetb ()
{
Mywrite ("In getb ()");
If(Monitor. Tryenter (resource_ B, 1000 ))
{
Mywrite ("Get resource_ B");
Thread. Sleep (1000 );
// Geta ();
If(Monitor. Tryenter (resource_a, 2000 ))
{
Monitor. Exit (resource_a );
}
Monitor. Exit (resource_ B );
Mywrite ("Exit resource_ B");
}
Else
{
Mywrite ("No has resource_ B");
}
}
// Custom printing method
Private Static voidMywrite (StringStr)
{
Console. Writeline (Thread. Currentthread. Name + Str );
}
}
The result is as follows:
ReferenceArticle:
Talking about the use of lock in C #: Jeff Wong
Monitor of synchronization technology Author: Galaxy messenger
Sample download