public final class Mutex extends Object
It is guaranteed that if you are a writer you can also enter the mutex as a reader. Conversely, if you are the only reader you can enter the mutex as a writer, but you'll be warned because it is very deadlock prone (two readers trying to get write access concurently).
If the mutex is used only by one thread, the thread can repeatedly enter it as a writer or reader. So one thread can never deadlock itself, whichever order operations are performed in.
There is no strategy to prevent starvation. Even if there is a writer waiting to enter, another reader might enter the section instead.
Examples of use:
Mutex m = new Mutex(); // Grant write access, compute an integer and return it: return m.writeAccess(new Mutex.Action<Integer>(){ public Integer run() { return 1; } }); // Obtain read access, do some computation, // possibly throw an IOException: try { m.readAccess(new Mutex.ExceptionAction<Void>() { public Void run() throws IOException { if (...) throw new IOException(); return null; } }); } catch (MutexException ex) { throw (IOException) ex.getException(); } // check whether you are already in read access if (m.isReadAccess()) { // do your work }
Modifier and Type | Class and Description |
---|---|
static interface |
Mutex.Action<T>
Action to be executed in a mutex without throwing any checked exceptions.
|
static interface |
Mutex.ExceptionAction<T>
Action to be executed in a mutex, possibly throwing checked exceptions.
|
static class |
Mutex.Privileged
Provides access to Mutex's internal methods.
|
Modifier and Type | Field and Description |
---|---|
static Mutex |
EVENT
Mutex that allows code to be synchronized with the AWT event dispatch thread.
|
Constructor and Description |
---|
Mutex()
Default constructor.
|
Mutex(Mutex.Privileged privileged) |
Mutex(Mutex.Privileged privileged,
Executor executor)
Constructor for those who wish to do some custom additional tasks
whenever an action or runnable is executed in the
Mutex . |
Mutex(MutexImplementation impl)
Creates
Mutex with given SPI. |
Mutex(Object lock) |
Modifier and Type | Method and Description |
---|---|
boolean |
isReadAccess()
Tests whether this thread has already entered the mutex in read access.
|
boolean |
isWriteAccess()
Tests whether this thread has already entered the mutex in write access.
|
void |
postReadRequest(Runnable run)
Posts a read request.
|
void |
postWriteRequest(Runnable run)
Posts a write request.
|
<T> T |
readAccess(Mutex.Action<T> action)
Run an action only with read access.
|
<T> T |
readAccess(Mutex.ExceptionAction<T> action)
Run an action with read access and possibly throw a checked exception.
|
void |
readAccess(Runnable action)
Run an action with read access, returning no result.
|
String |
toString()
toString
|
<T> T |
writeAccess(Mutex.Action<T> action)
Run an action with write access.
|
<T> T |
writeAccess(Mutex.ExceptionAction<T> action)
Run an action with write access and possibly throw an exception.
|
void |
writeAccess(Runnable action)
Run an action with write access and return no result.
|
public static final Mutex EVENT
When the Mutex methods are invoked on this mutex, the methods' semantics change as follows:
Mutex.isReadAccess()
and Mutex.isWriteAccess()
methods
return true
if the current thread is the event dispatch thread
and false otherwise.
Mutex.postReadRequest(java.lang.Runnable)
and Mutex.postWriteRequest(java.lang.Runnable)
methods
asynchronously execute the Runnable
passed in their
run
parameter on the event dispatch thead.
Mutex.readAccess(java.lang.Runnable)
and
Mutex.writeAccess(java.lang.Runnable)
methods asynchronously execute the
Runnable
passed in their run
parameter
on the event dispatch thread, unless the current thread is
the event dispatch thread, in which case
run.run()
is immediately executed.
Mutex.readAccess(Mutex.Action)
,
Mutex.readAccess(Mutex.ExceptionAction action)
,
Mutex.writeAccess(Mutex.Action action)
and
Mutex.writeAccess(Mutex.ExceptionAction action)
methods synchronously execute the Mutex.ExceptionAction
passed in their action
parameter on the event dispatch thread,
unless the current thread is the event dispatch thread, in which case
action.run()
is immediately executed.
Since version 9.18 the methods of the EVENT
instance properly
understand semantics of Lookups.executeWith(org.openide.util.Lookup, java.lang.Runnable)
method and propagate the effective Lookup
to the event dispatch
thread.
public Mutex(MutexImplementation impl)
Mutex
with given SPI.impl
- the Mutex
SPI.public Mutex(Object lock)
public Mutex()
public Mutex(Mutex.Privileged privileged)
privileged
- can enter privileged states of this Mutex
This helps avoid creating of custom Runnables.public Mutex(Mutex.Privileged privileged, Executor executor)
Mutex
. This
may be useful for wrapping all the actions with custom ThreadLocal
value, etc. Just implement the Executor
's execute(Runnable)
method and do pre and post initialization tasks before running the runnable.
The Executor.execute(java.lang.Runnable)
method shall return only when the passed in
Runnable
is finished, otherwise methods like Mutex.readAccess(Action)
and co.
might not return proper result.
privileged
- can enter privileged states of this Mutexexecutor
- allows to wrap the work of the mutex with a custom codepublic <T> T readAccess(Mutex.Action<T> action)
T
- type of actionaction
- the action to performMutex.Action.run()
public <T> T readAccess(Mutex.ExceptionAction<T> action) throws MutexException
MutexException
and thrown from this method. One is encouraged
to catch MutexException
, obtain the inner exception, and rethrow it.
Here is an example:
try {
mutex.readAccess (new ExceptionAction () {
public void run () throws IOException {
throw new IOException ();
}
});
} catch (MutexException ex) {
throw (IOException) ex.getException ();
}
Note that runtime exceptions are always passed through, and neither
require this invocation style, nor are encapsulated.T
- type of actionaction
- the action to executeMutex.ExceptionAction.run()
MutexException
- encapsulates a user exceptionRuntimeException
- if any runtime exception is thrown from the run methodMutex.readAccess(Mutex.Action)
public void readAccess(Runnable action)
action
- the action to performMutex.readAccess(Mutex.Action)
public <T> T writeAccess(Mutex.Action<T> action)
T
- type of actionaction
- the action to performMutex.Action.run()
public <T> T writeAccess(Mutex.ExceptionAction<T> action) throws MutexException
try {
mutex.writeAccess (new ExceptionAction () {
public void run () throws IOException {
throw new IOException ();
}
});
} catch (MutexException ex) {
throw (IOException) ex.getException ();
}
T
- type of actionaction
- the action to executeMutex.ExceptionAction.run()
MutexException
- an encapsulated checked exception, if anyRuntimeException
- if a runtime exception is thrown in the actionMutex.writeAccess(Mutex.Action)
,
Mutex.readAccess(Mutex.ExceptionAction)
public void writeAccess(Runnable action)
action
- the action to performMutex.writeAccess(Mutex.Action)
,
Mutex.readAccess(Runnable)
public boolean isReadAccess()
readAccess
will be executed immediatelly
without any blocking.
Calling postWriteAccess
will delay the execution
of its Runnable
until a readAccess section is over
and calling writeAccess
is strongly prohibited and will
result in a warning as a deadlock prone behaviour.
Warning: since a thread with write access automatically has effective read access as well (whether or not explicitly requested), if you want to check whether a thread can read some data, you should check for either kind of access, e.g.:
assert myMutex.isReadAccess() || myMutex.isWriteAccess();
public boolean isWriteAccess()
writeAccess
will be executed
immediatelly without any other blocking. postReadAccess
will be delayed until a write access runnable is over.public void postReadRequest(Runnable run)
Warning: this method blocks.
run
- runnable to runpublic void postWriteRequest(Runnable run)
Warning: this method blocks.
run
- runnable to run