This class allows mutual exclusive access to resources shared by different threads. In other words, access to certain data that is accessed by different threads, can be protected if each thread (aka critical section code) uses the same ThreadLock to control the access to such data.
If an Acquire is not followed by a corresponding Release, other threads will not be able to gain control to this object and will wait endlessly (deadlock situation). To avoid this, it is a good practice to embed pairs of Acquire()/Release() calls into try/finally statements as follows:
try { tl.Acquire(); ...critical section code .... } finally { tl.Release() }
ThreadLock uses an internal counter to allow multiple calls to Acquire() and to be freed only when a same amount of Release() calls are performed. This behavior can be switched off by a constructor parameter. If switched off, each recursive Acquire() call will not be counted and each call to Release() will instantly free the mutex. This mode is not very recommended, the standard use is recursive mode.
Furthermore, ThreadLock allows to disable locking using setUnsafe(). The objective here is to gain execution speed, as thread synchronization causes relatively expensive system calls. Nevertheless, it is sometimes obvious that the same code may run in a thread safe mode one time and without thread locking the next time. Therefore, for performance critical code, it is quite useful to be able to control this behavior.
Caution: Use this class with great care. Deadlocks are not easy to detect and debug. Use this class only if standard synchronization of the Java language seems too limited and mechanisms like the class uses internally would need to be implemented.
Public Fields | |
int | RecursionWarningThreshold =10 |
int | waitWarningTimeLimitInMillis =1000 |
Public Methods | |
ThreadLock (LockMode lockMode=LockMode.Recursive, Safeness safeness=Safeness.Safe) | |
virtual void | Acquire ([CallerLineNumber] int cln=0,[CallerFilePath] String csf="",[CallerMemberName] String cmn="") |
int | DbgCountAcquirements (Thread thread=null) |
LockMode | GetMode () |
Safeness | GetSafeness () |
virtual void | Release () |
void | SetSafeness (Safeness safeness) |
override String | ToString () |
bool | WillRelease () |
Protected Fields | |
int | cntAcquirements |
LockMode | lockMode |
Object | mutex |
Thread | owner |
Ticks | waitTime =new Ticks() |
|
inline |
Create a ThreadLock that allows recursion. A warning will be given (ALIB Error) when the given recursion level is reached (and each multiple of it). In addition the lock can be initialized to be unsafe, which means the locking critical sections is disabled.
lockMode | (Optional) Flag if recursion support is on (the default). If not, nested locks are not counted. |
safeness | (Optional) Defaults to Safeness.Safe . See SetSafeness for more information. |
|
inlinevirtual |
Thread which invokes this method gets registered as the current owner of this object, until the same thread releases the ownership invoking Release(). In the case that this object is already owned by another thread, the invoking thread is suspended until ownership can be gained. Multiple (nested) calls to this method are counted and the object is only released when the same number of Release() calls have been made.
cln | (Optional) Caller info, compiler generated. Please omit. |
csf | (Optional) Caller info, compiler generated. Please omit. |
cmn | (Optional) Caller info, compiler generated. Please omit. |
Reimplemented in Lox.
|
inline |
Returns the number of acquirements of this ThreadLock. The negative number (still providing the number of acquirements) is returned if the owning thread is not the same as the given one.
thread | The thread to test current ownership of this. Defaults to the current (invoking) thread. |
|
inline |
Query if this instance was set to work recursively.
|
inline |
Query if this instance was set to unsafe mode.
|
inlinevirtual |
|
inline |
If parameter is true, the whole locking system is disabled. The only objective here is to to gain execution speed, as thread synchronization causes relatively expensive system calls. Use this method only if you are 100% sure that your (otherwise) critical section are executed in a single threaded environment. And: "relative expensive" means: they are not really expensive. This is provided only for the rare case that your critical section is very, very frequently executed.
safeness | Determines if this object should use a mutex (Safeness.Safe ) or just do nothing (Safeness.Unsafe ). |
|
inline |
This is for debugging purposes. E.g. this enables the Monodevelop IDE to display object descriptions in the debugger.
|
inline |
Returns true
if the next invocation of Release will release the lock. Returns false
, if recursive acquirements have been performed.
true
if locked exactly once.
|
protected |
Counter for the number of Acquire() calls of the current thread.
|
protected |
Flag if recursion support is on. If not, nested locks are not counted.
|
protected |
The internal object to lock on.
|
protected |
The current owner of the ThreadLock.
int RecursionWarningThreshold =10 |
Limit of recursions. If limit is reached or a multiple of it, an error is passed to ReportWriter. Defaults is 10.
int waitWarningTimeLimitInMillis =1000 |
This is a threshold that causes Acquire() to send a warning to ReportWriter if acquiring the access takes longer than the given number of milliseconds. To disable such messages, set this value to 0. Default is 1 second.