This article is original. If you need to reprint it, please indicate the author and the source. Thank you!
Previous: C # thread series (4): synchronization and deadlock
In the previous lecture, we introduced the usageLockTo synchronize threads. Actually, thisLockYesC #InC #Compiler CompilationLockStatement, compile it into a callMonitorClass. Let's take a look at the followingC #Source code:
Public Static VoidMylock ()
{
Lock(Typeof(Program ))
{
}
}
The aboveCodePassLockStatement enablingMylockSynchronization, this method is compiledIlCode1.
Figure1
From the marked area, we can see that one Lock The statement is compiled into a call. Monitor Of Enter And Exit Method. Monitor In System. threadingNamespace. Lock Is equivalent to directly calling Monitor Of Entry Method, the difference is, Lock The method is automatically unlocked after it is completed. Il Is called Monitor Of Exit Method, but in C # Program, It seems to be automatically unlocked, which is similar C # In Using Statement to automatically release resources such as databases. However C # Use in source program MonitorClass, you must call Exit Method To explicitly unlock the lock. The following code is used:
Monitor. Entry (lockobj );
Try
{
// Same layout of lockobj
}
Catch (Exception E)
{
// Exception Handling Code
}
Finally
{
Monitor. Exit (lockobj ); // Unlock
}
ExitFinallyFinallyIn this way, no matter in the exception, return or normal execution of the method,FinallyAnd callExitMethod to unlock.
MonitorClasses can not only be completely replacedLockStatement (if you only useLockIt is best to directly use the functions of the statement itself.LockStatement), you can also useTryentryMethod to set a lock timeout, in milliseconds. The following code is used:
If (Monitor. tryentry (lockobj, 1000 ))
{
Try
{
}
Finally
{
Monitor. Exit (lockobj );
}
}
Else
{
// Processing code after timeout
}
The above Code sets the lock timeout1Second, that is, in1Seconds later,LockobjNot unlocked yet,TryentryThe method returnsFalseIf1Within seconds,LockobjUnlocked,TryentryReturnTrue. We can use this method to avoid deadlocks, as shown in the following code:
Class Program
{
Private Static Object obja = New Object ();
Private Static Object objb = New Object ();
Public Static Void Locka ()
{
If (Monitor. tryenter (obja, 1000 ))
{
Thread. Sleep ( 1000 );
If (Monitor. tryenter (objb, 2000 ))
{
Monitor. Exit (objb );
}
Else
{
Console. writeline ( " Lockb timeout " );
}
Monitor. Exit (obja );
}
Console. writeline ( " Locka " );
}
Public Static Void Lockb ()
{
If (Monitor. tryenter (objb, 2000 ))
{
Thread. Sleep ( 2000 );
If (Monitor. tryenter (obja, 1000 ))
{
Monitor. Exit (obja );
}
Else
{
Console. writeline ( " Locka timeout " );
}
Monitor. Exit (objb );
}
Console. writeline ( " Lockb " );
}
Public Static Void Main ()
{
Thread threada = New Thread (Locka );
Thread threadb = New Thread (lockb );
Threada. Start ();
Threadb. Start ();
Thread. Sleep ( 4000 );
Console. writeline ( " Thread end " );
}
}
The above code is an example of a deadlock in the previous section.LockStatement changedTryentryMethod, and set the lock expiration time, because after waiting for a certain period of time, no matter whether the locked object is unlocked,TryentryThe above code will not be deadlocked. Result of running the above Code2.
Figure2
IfTryentryThe method timeout isSystem. Threading. Timeout. Infinite,TryentryThe method is equivalentEntryMethod. If the timeout value is0, Whether or not to unlock,TryentryMethods are returned immediately.