1. Introduction
This blog describes the use of Wait,notify,notifyall in Java by implementing a bounded container. These keywords use the probability is not high, but read some source code when still often encounter, write to enhance memory.
Specific production practices, for me I do not recommend that programmers directly use these, JAVA1.5 after the provision of a lot of directly available thread-safe containers, can write less code less code, reduce the need for testing,
Also reduce the likelihood of errors.
2. A thread-safe stack with limited capacity
First paste the code:
Package com.sabo.concurrent;/** * Created by Canbin.zhang on 2016/3/29. */public class Sabostack {private final int[] _data; public sabostack (int limit) {_data = new Int[limit]; } private Final Object lock = new Object (); private int size = 0; public void push (int v) {synchronized (lock) {while (size >= _data.length) {try { Lock.wait (); } catch (Interruptedexception e) {e.printstacktrace (); }} _data[size] = V; ++size; Lock.notifyall (); }} public int pop () {int v; Synchronized (lock) {while (size = = 0) {try {lock.wait (); } catch (Interruptedexception e) {e.printstacktrace (); }} v = _data[size-1]; --size; Lock.notifyall (); Return V } }}
If the capacity of the stack is unlimited, in fact, the implementation as long as the Synchronized keyword can be achieved, but most of the time the use of memory is always limited, such as the stack can only use up to 10 int size space, so that implementation requires more consideration of a logic " What happens when there are no elements in the stack? When the stack is full of space what to do with it? ”。
In Java, a mechanism is given to invoke the wait method when it encounters this condition, causing the calling thread to be placed in the waiting queue, and the condition may be satisfied when the situation changes.
The use of wait basically takes a fixed pattern:
Synchronized (lock) { while (/* condition */) { try { lock.wait (); } catch (Interruptedexception e) { E.printstacktrace (); } } Other processing code after the condition is met
1). After the Lock.wait () method call, the current thread discards the lock it occupies so that other threads have the opportunity to change the current state.
2). Notice that the condition is full and not satisfied using while instead of if, because the condition is not satisfied after the current thread is awakened.
3). The difference between notify and Notifyall: Notify wakes up a thread in the waiting queue, Notifyall wakes up all the threads in the waiting queue, what can you think of? Notify the thread that wakes up cannot change the condition what to do, which could lead to a deadlock.
Another conceivable problem is that notify and notifyall do not indicate which threads should be awakened, causing the non-waking thread to enter the waiting queue, which results in a lower efficiency.
Here, for example, I want to wake up the thread that was placed in the waiting queue because of stack empty when the number of elements in stack size >= 1.
Class SaboStack2 {Private final int[] _data; private int size = 0; public SaboStack2 (int limit) {_data = new Int[limit]; } private Final Reentrantlock lock = new Reentrantlock (); Private final Condition Lock_empty = Lock.newcondition (); Private final Condition lock_full = Lock.newcondition (); public void push (int v) {lock.lock (); while (size >= _data.length) {try {lock_full.await (); } catch (Interruptedexception e) {e.printstacktrace (); }} _data[size] = V; ++size; Lock_empty.signalall (); Lock.unlock (); } public int pop () {int v; Lock.lock (); while (size = = 0) {try {lock_empty.await (); } catch (Interruptedexception e) {e.printstacktrace (); }} v = _data[size-1]; --size; Lock_full.signalall (); Lock.unlock (); return v; } }
The condition lock is used here to divide the waiting threads into two groups, with a degree of differentiation that can improve efficiency to some extent.
If you are a Linux programmer familiar with pthread_cond_wait may prefer the second way of implementation, but should still look not accustomed to, to make a waiting queue such a thing how to see a bit of egg pain.
Implementation of thread-safe bounded containers in Java