Java Multithreading Series--"Juc lock" 06 of the condition conditions
Overview
In front of the JUC package, the principle of the lock is introduced, this chapter will be JUC in conjunction with the lock is often used in condition to introduce, the content includes:
Condition Introduction
List of condition functions
condition Example
Reprint Please specify source:http://www.cnblogs.com/skywang12345/p/3496716.html
Condition Introduction
The role of condition is to control the lock more precisely. The await () method in condition is equivalent to the wait () method of object, and the signal () method in condition is equivalent to the Notify () method of object, condition in Signalall () The Notifyall () method equivalent to object. The difference is that the wait (), notify (), and Notifyall () methods in object are used in bundles with the "Sync lock" (synchronized keyword), whereas condition is required with a "mutex"/"shared lock" bundle.
List of condition functions
Causes the current thread to wait until it receives a signal or is interrupted. void await ()//causes the current thread to wait until it receives a signal, is interrupted, or arrives at a specified wait time. The Boolean await (long time, timeunit unit)//causes the current thread to wait until it receives a signal, is interrupted, or arrives at a specified wait time. Long Awaitnanos (long nanostimeout)//causes the current thread to be in a wait state until the signal is received. void awaituninterruptibly ()//causes the current thread to wait until it receives a signal, is interrupted, or arrives at a specified deadline. The Boolean awaituntil (Date deadline)//wakes up a waiting thread. void signal ()//wakes up all waiting threads. void Signalall ()
Condition Example
Example 1 shows the sleep/wake feature of a thread through the wait (), notify () object.
Example 2 shows the sleep/wake feature of a thread through condition's await (), signal ().
Example 3 is an advanced feature through condition.
Example 1
public class WaitTest1 {public static void main (string[] args) {Threada ta = new Threada ("ta"); Synchronized (TA) {///through synchronized (TA) get "The synchronization lock of object Ta" try {System.out.println (Thread.currentthre AD (). GetName () + "Start Ta"); Ta.start (); System.out.println (Thread.CurrentThread (). GetName () + "block"); Ta.wait (); Wait for System.out.println (Thread.CurrentThread (). GetName () + "continue"); } catch (Interruptedexception e) {e.printstacktrace (); }}}} Static class Threada extends thread{public Threada (String name) {super (name); public void Run () {synchronized (this) {///synchronized (this) gets the "synchronization lock for current object" System . Out.println (Thread.CurrentThread (). GetName () + "wakup others"); Notify (); Wake "Wait thread on current object"}}}}
Example 2
Import Java.util.concurrent.locks.lock;import Java.util.concurrent.locks.condition;import Java.util.concurrent.locks.reentrantlock;public class ConditionTest1 {private static lock lock = new Reentrant Lock (); private static Condition Condition = Lock.newcondition (); public static void Main (string[] args) {Threada ta = new Threada ("ta"); Lock.lock (); Get lock try {System.out.println (Thread.CurrentThread (). GetName () + "Start Ta"); Ta.start (); System.out.println (Thread.CurrentThread (). GetName () + "block"); Condition.await (); Wait for System.out.println (Thread.CurrentThread (). GetName () + "continue"); } catch (Interruptedexception e) {e.printstacktrace (); } finally {Lock.unlock (); Release Lock}} static class Threada extends thread{public Threada (String name) {super (name); } public void Run () {lock.lock (); Get lock try {System.out.println (Thread.CurrentThread (). GetName () + "wakup others"); Condition.signal (); Wake up "Other threads where the condition is locked"} finally {Lock.unlock (); Release Lock}}}}
Operation result :
Main start Tamain Blockta wakup Othersmain continue
With Example 1 and Example 2, we know that the condition and object methods have a corresponding relationship:
Object hibernate wait await notify signal wake all Threads Notifyall Signalall
In addition to supporting the above features, condition is more powerful in that it can control the sleep and wake of multiple threads more finely. For the same lock, we can create multiple condition and use different condition in different situations.
For example, if the multithreading reads/writes the same buffer: when the data is written to the buffer, the "read thread" is awakened, the "Write thread" is awakened after the data is read from the buffer, and the "Write thread" waits when the buffer is full, and the "read thread" waits when the buffer is empty. If wait () in the object class is used, notify (), Notifyall () implements the buffer, it is not possible to wake "read threads" with explicit specified notify () or Notifyall () when the data is written to the buffer, You can only wake all threads through Notifyall (but Notifyall cannot distinguish whether the thread that wakes up is a read thread or a write thread). However, by condition, you can explicitly specify the wake-up read thread.
Consider the following example 3, which may have a deeper understanding of the concept.
Example 3
Import Java.util.concurrent.locks.lock;import Java.util.concurrent.locks.condition;import Java.util.concurrent.locks.reentrantlock;class Boundedbuffer {Final lock lock = new Reentrantlock (); Final Condition notfull = Lock.newcondition (); Final Condition notempty = Lock.newcondition (); Final object[] items = new OBJECT[5]; int Putptr, takeptr, Count; public void put (Object x) throws Interruptedexception {Lock.lock (); Get lock try {//If buffer is full, wait until buffer is not full before adding X to the buffer. while (count = = items.length) notfull.await (); Add x to buffer items[putptr] = x; Set the put statistic to putptr+1, or putptr to 0 if buffer is full. if (++putptr = = items.length) putptr = 0; The number of "buffers" will be +1 ++count; Wake the take thread because the take thread waits for notempty.signal () through notempty.await (); Prints the data written to System.out.println (Thread.CurrentThread (). GetName () + "put" + (Integer) x); } Finally {lock.unlock (); Release Lock}} public Object take () throws Interruptedexception {Lock.lock (); Get lock try {//If buffer is empty, wait until buffer is not empty to remove X from buffer. while (count = = 0) notempty.await (); Remove x from the buffer Object x = items[takeptr]; "Take statistics takeptr+1" and if "buffer is empty", set Takeptr to 0. if (++takeptr = = items.length) takeptr = 0; Will "buffer" quantity-1--count; Wakes up the put thread because the put thread waits for notfull.signal () through notfull.await (); Print out the Data System.out.println (Thread.CurrentThread (). GetName () + "take" + (Integer) x); return x; } finally {Lock.unlock (); Release Lock}}}public class ConditionTest2 {private static Boundedbuffer BB = new Boundedbuffer (); public static void Main (string[] args) {//start 10 "Write Threads", write data to Boundedbuffer continuously (write 0-9);//Start 10 "Read Threads", from Boundedb Reading data continuously in the Uffer. For (int i=0; i<10; i++) {New Putthread ("P" +i, I). Start (); New Takethread ("T" +i). Start (); }} static Class Putthread extends Thread {private int num; Public Putthread (String name, int num) {super (name); This.num = num; } public void Run () {try {thread.sleep (1); Thread hibernation 1ms bb.put (num); Write data to Boundedbuffer} catch (Interruptedexception e) {}}} static Class Takethread Extends Thread {public takethread (String name) {super (name); } public void Run () {try {thread.sleep (10); Thread hibernation 1ms Integer num = (integer) bb.take (); Fetch data from boundedbuffer} catch (Interruptedexception e) {}}}}
Run results (one time) :
P1 put 1p4 put 4p5 put 5p0 put 0p2 put 2t0 take 1p3 put 3t1 take 4p6 put 6t2 take 5P7 put
7t3 take 0P8 put 8t4 take 2p9 put 9t5 take 3t6 take 6t7 take 7t8 take 8t9 take 9
Result Description :
Boundedbuffer is a buffer with a capacity of 5, which stores object objects in the buffer and supports multi-threaded read/write buffering. When multiple threads manipulate "one Boundedbuffer object", they mutually exclusive access to the buffer items through the mutex lock, and all threads under the same Boundedbuffer object share "Notfull" and "Notempty" These two condition.
The notfull is used to control write buffering, and Notempty is used to control read buffering. When the buffer is full, the thread that calls put will execute notfull.await () to wait, when the buffer is not full, add the object to the buffer and count+1 the buffer capacity, and finally, call Notempty.signal () Buffer the waiting thread on the Notempty (calling Notempty.await's thread). In short, notfull controls "write to buffer" and wakes the waiting thread on notempty after writing data to the buffer.
Similarly, notempty controls "read buffer", which wakes the waiting thread on Notfull when the buffer data is read.
(02) In the main function of ConditionTest2, 10 "Write Threads" are started, the data is written to Boundedbuffer continuously (0-9), and 10 "read Threads" are started, and the data is read continuously from Boundedbuffer.
(03) Simple analysis of the results of the operation.
1, the P1 thread writes 1 to the buffer. at this point, the buffer data: | 1 | | | | | 2, the P4 thread writes 4 to the buffer. at this point, the buffer data: | 1 | 4 | | | | 3, the P5 thread writes 5 to the buffer. at this point, the buffer data: | 1 | 4 | 5 | | | 4, the P0 thread writes 0 to the buffer. at this point, the buffer data: | 1 | 4 | 5 | 0 | | 5, the P2 thread writes 2 to the buffer. at this point, the buffer data: | 1 | 4 | 5 | 0 | 2 | At this point, the buffer capacity is 5 and the buffer is full! If, at this time, there are "write threads" that want to write data to the buffer, the notfull.await () wait in the put is called and the direct buffer is not full to continue running. 6, the t0 thread pulls the data out of the buffer 1. At this point, buffer data: | | 4 | 5 | 0 | 2 | 7, the P3 thread writes 3 to the buffer. at this point, the buffer data: | 3 | 4 | 5 | 0 | 2 | 8, the T1 thread pulls the data out of the buffer 4. At this point, buffer data: | 3 | | 5 | 0 | 2 | 9, the P6 thread writes 6 to the buffer. at this point, the buffer data: | 3 | 6 | 5 | 0 | 2 | ...
Java-"JUC" of the Condition source code analysis