Each period summarizes a small knowledge point and related interview questions, hey hey, and we learn together.
There is a class in GUC that we use less often, but it is an indispensable member of many classes. He is Condition.
True or false: True or false: True or false Condition acts as a multithreaded shared identifier that blocks when true passes and when false waits.
1. Use of Condition
You can see how to use it in the following code.
// thread 1
System.out.println("1 am thread 1 start");
condition.await();/ / blocking
System.out.println("1 am thread 1 end");
// thread 2
System.out.println("1 am thread 2");
condition.signal():/ / wake
Copy the code
Suppose thread 1 and thread 2 execute concurrently. The output after execution would be:
1 am thread 1 start
1 am thread 2
1 am thread 1 end
Copy the code
Similar to wait(),notify() for an Object. The only difference is that the Condition does not require the Synchronize modification first to invoke the blocking method. Does that make it easier to use? The judgement of empty and full in the blocking queue is realized based on Condition, which can guarantee the order of notification.
2. Principle of Condition
A Condition instance is essentially bound to a lock. To get a Condition instance of a particular Condition instance, use its newCondition() method.
final Lock lock = new ReentrantLock();
// Need to bind to lock
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
Copy the code
2.1 Condition API
Modifier and Type | Method and Description |
---|---|
void |
await() Causes the current thread to wait to signal orinterrupted 。 |
boolean |
await(long time, TimeUnit unit) Causes the current thread to wait until signaled or interrupted, or the specified wait time has elapsed. |
long |
awaitNanos(long nanosTimeout) Causes the current thread to wait until signaled or interrupted, or the specified wait time has elapsed. |
void |
awaitUninterruptibly() Causes the current thread to wait until signaled. |
boolean |
awaitUntil(Date deadline) Causes the current thread to wait until signaled or interrupted, or until a specified deadline has passed. |
void |
signal() Wake up a waiting thread. |
void |
signalAll() Wake up all waiting threads. |
2.1 Condition to realize
Initialization method:
final ConditionObject newCondition(a) {
ConditionObject is the inner class of AQS, from which attributes and methods from the outer class can be called
return new ConditionObject();
}
Copy the code
Let’s first look at the await method, which blocks wait:
public final void await(a) throws InterruptedException {
If the current thread is interrupted, InterruptedException is thrown
if (Thread.interrupted())
throw new InterruptedException();
Condition = Condition; Condition = Condition; Condition = Condition; Condition = Condition
Node node = addConditionWaiter();
// Release with node's current state value; Return to save state
int savedState = fullyRelease(node);
int interruptMode = 0;
// Is the queue synchronized? IsOnSyncQueue returns true if the next Node is not empty, meaning that thread blocking is performed on the first non-LCH Node.
while(! isOnSyncQueue(node)) {// The current thread is blocked
LockSupport.park(this);
// Check whether there is an interruption
if((interruptMode = checkInterruptWhileWaiting(node)) ! =0)
break;
}
// Interrupt status processing
if(acquireQueued(node, savedState) && interruptMode ! = THROW_IE) interruptMode = REINTERRUPT;// Node cleanup
if(node.nextWaiter ! =null) // clean up if cancelled
unlinkCancelledWaiters();
// 0 is the default state
if(interruptMode ! =0)
/ / the interrupt processing
reportInterruptAfterWait(interruptMode);
}
private Node addConditionWaiter(a) {
Node t = lastWaiter;
// If lastWaiter is cancelled, clean out.
if(t ! =null&& t.waitStatus ! = Node.CONDITION) { unlinkCancelledWaiters(); t = lastWaiter; }// Create a Node in condition
Node node = new Node(Thread.currentThread(), Node.CONDITION);
if (t == null)
firstWaiter = node;
else
t.nextWaiter = node;
lastWaiter = node;
return node;
}
final int fullyRelease(Node node) {
boolean failed = true;
try {
int savedState = getState();
if (release(savedState)) {
failed = false;
return savedState;
} else {
throw newIllegalMonitorStateException(); }}finally {
if(failed) node.waitStatus = Node.CANCELLED; }}Copy the code
Let’s see how signal wakes up Node:
public final void signal(a) {
GetExclusiveOwnerThread () == thread.currentThread ();
if(! isHeldExclusively())throw new IllegalMonitorStateException();
Node first = firstWaiter;
// Nodes that are waiting need to be woken up
if(first ! =null)
doSignal(first);
}
private void doSignal(Node first) {
do {
if ( (firstWaiter = first.nextWaiter) == null)
lastWaiter = null;
first.nextWaiter = null;
// Move the node from conditional queue to synchronous queue.
} while(! transferForSignal(first) && (first = firstWaiter) ! =null);
}
final boolean transferForSignal(Node node) {
/* * If cannot change waitStatus, the node has been cancelled. */
if(! compareAndSetWaitStatus(node, Node.CONDITION,0))
return false;
/* * Splice onto queue and try to set waitStatus of predecessor to * indicate that thread is (probably) waiting. If cancelled or * attempt to set waitStatus fails, wake up to resync (in which * case the waitStatus can be transiently and harmlessly wrong). */
Node p = enq(node);
int ws = p.waitStatus;
if (ws > 0| |! compareAndSetWaitStatus(p, ws, Node.SIGNAL))// unpark wakes up the thread
LockSupport.unpark(node.thread);
return true;
}
Copy the code
Condition 3
3.1. What is Java false wake up and how to avoid false wake up?
False awaken
When a condition is met, many threads are awakened, but only some of them are useful awakenings. The rest are useless
For example, if an item has no goods and suddenly enters an item, all threads are awakened, but only one person can buy it, so everyone else is falsely awakened and cannot acquire the lock of the object
How to avoid false awakenings
When all threads are awakened, the critical condition is checked using while judgment, so that when the thread is awakened, the condition can be checked again.
3.2. When are Mutex and BooleanLatch used
Mutex: This is a non-reentrant Mutex class that uses zero to indicate unlocked status and one to indicate locked status. While non-reentrant locking does not strictly require logging the current owner thread, it nevertheless makes usage easier to monitor. It also supports conditions and exposes one of the instrumentation methods
BooleanLatch: This is a latch class similar to CountDownLatch, except that it only needs a signal to trigger
3.3 Differences between CLH lock and MCS lock
- In terms of code implementation, CLH is much simpler than MCS.
- In terms of spin conditions, CLH spins on attributes of the precursor node, while MCS spins on local attribute variables.
- From the view of linked list queue, CLHNode does not directly hold the precursor node, CLH lock release only need to change its own attributes; McSnodes directly hold their successor nodes. The MCS lock release requires changing the properties of the successor nodes.
- CLH lock release only needs to change its own properties, MCS lock release requires to change the properties of subsequent nodes
3.4 What are the states of Node
- CANCELLED(1) : indicates that the current node has been CANCELLED. When timeout or interrupted (in response to an interrupt), a change is triggered to this state, and the node will not change after entering this state.
- SIGNAL(-1) : indicates that the successor node is waiting for the current node to wake up. When a successor node joins the queue, its status is updated to SIGNAL.
- CONDITION(-2) : indicates that the node is waiting on CONDITION. When another thread calls CONDITION signal(), the node in CONDITION will be transferred from the waiting queue to the synchronization queue, waiting for the synchronization lock.
- PROPAGATE(-3) : In the shared mode, not only does the previous parent node wake up the subsequent one, but it may also wake up the subsequent one.
- 0: indicates the default state when a new node joins the queue.
Scan the QR code to follow the public account “Ape Must Pass”
Answer the “interview questions” and collect them yourself.
Wechat group for discussion, please add wechat account: zyhui98, note: interview questions add group
This article is published by YBG. Unauthorized reprint is prohibited. Violators are subject to legal liability