Multi-producer and multi-consumer issues
To produce steamed bread consumption steamed bread as an example.
Class Resource {private String name;private int count = 1;private Boolean flag = false;public synchronized void set (String Name) {if (flag) {try {this.wait ()},} catch (Exception e) {//Todo:handle Exception}}this.name = name + count;count++; System.out.println (Thread.CurrentThread (). GetName () + "---producer----" +this.name); flag = True;notify ();} Public synchronized void out () {if (!flag) {try {this.wait ();} catch (Exception e) {//Todo:handle EXCEPTION}}SYSTEM.OUT.P Rintln (Thread.CurrentThread (). GetName () + "---------consumer--------" +this.name); flag = False;notify ();}} Class Producer implements Runnable{private Resource R; Producer (Resource r) {THIS.R = R;} public void Run () {while (true) {r.set ("steamed bun");}}} Class Consumer implements Runnable{private Resource R; Consumer (Resource r) {THIS.R = R;} public void Run () {while (true) {R.out ()}}} public class Main {public static void main (string[] args) {Resource r = new Resource (); Producer Pro = new Producer (r); Consumer con = new Consumer (r); Thread t0 = new Thread (PRO); Thread T1 = new Thread (PRO); Thread t2 = new Thread (con); thread t3 = new Thread (con); T0.start (); T1.start (); T2.start (); T3.start ();}}
The above code is prone to a problem, that is, the same steamed bread has been consumed several times, or some steamed bread has not been consumed. Single-born, single consumer does not have this problem
Cause: Notify wake-up thread is any one, such as T0 T1 are waiting state, T0 alive, T1 may also be awakened, so there will be a number of steamed bread without being consumed, in response to this problem, flag judgment can be changed to cycle, so it is easy to cause a deadlock situation: T0 T1 was wait, T2 normal consumption once, flag = False, Wake up T0, because the loop T2 T3 was wait, t0 execute once, flag = True, assuming wake T1, Judge T0 to Wait,while,t1 also entered the waiting, deadlock state
PS: The frozen state of the thread is awakened after this time do not participate in the judgment, down execution, so simply, a number of steamed bread is not produced by the consumption problem, is because the frozen state of the thread no longer continue to participate in the judgment caused, and the deadlock is caused by the cyclic judgment
Multi-production multi-consumption problem solving:
notify, instead of Notifyall, the current class of threads in a normal execution, wake all threads, the current same kind of thread because while, nature will continue to wait, the other side of any thread execution once, the other side remaining The thread continues to wait, thus enabling the generation of the corresponding consumption
Class Resource {private String name;private int count = 1;private Boolean flag = false;public synchronized void set (String Name) {while (flag) {try {this.wait ();} catch (Exception e) {//Todo:handle Exception}}this.name = name + count;count++;s Ystem.out.println (Thread.CurrentThread (). GetName () + "---producer----" +this.name); flag = True;notifyall ();} Public synchronized void out () {while (!flag) {try {this.wait ()} catch (Exception e) {//Todo:handle Exception}}system.ou T.println (Thread.CurrentThread (). GetName () + "---------consumer--------" +this.name); flag = False;notifyall ();}}
Summarize:
If judgment, will only be judged once, easy to cause the thread should not wake up, there is a problem
While determining whether to run after the thread gets the execution right
Notify, can only wake up any one thread, but wake the local thread, meaningless, and while+notify = deadlock
Notifyall, resolves that the thread of this party will surely wake the other thread
Therefore, multi-production and multi-consumption problem = while + Notifyall, but also caused inefficient problem (this party should not wake up, also wake up)
New features (JDK1.5 upgrade)
How do I not wake the party and wake the other one?
void Fu ()//early {synchronized (obj)//about the operation of the lock is implicit, only the lock itself knows {code ...}} Post-upgrade, the lock is encapsulated as Object lock L = new Reentrantlock (), the implicit way to manipulate the lock is defined in the object void Fu () {l.lock ();//Get Lock code: L.unlock ();//Release Lock}
Interface Lock
Lock
Implementations provide a wider synchronized
range of locking operations than can be obtained using methods and statements. This implementation allows for a more flexible structure that can have very different properties and can support multiple related Condition
objects.
Condition
The Object
monitor methods ( wait
, notify
and notifyAll
) are decomposed into distinct objects to Lock
provide multiple wait sets (Wait-set) for each object by combining these objects with any implementation. This replaces the use of Lock
synchronized
methods and statements, Condition
replacing the use of the Object monitor method.
Lock L = ...; L.lock (); try { //access the resource protected by this lock } finally { l.unlock (); }
Lock interface: Replaces the synchronous code block or the synchronization function, the implicit operation of the synchronous lock becomes a real operation, more flexible, can be a lock plus multiple monitors
Method:
L.lock ();//Get Lock
L.unlock ();//release lock, generally with the finally block of code
Condition interface: Implements the Wait (), notify (), Notifyall () methods in object, which are individually encapsulated by these monitor methods and become Condition monitor objects, which can be combined with arbitrary locks
Await () equals wait
Signal () equivalent to notify
Signalall (); Equivalent to Notifyall
Import Java.util.concurrent.locks.*;class Resource {private String name;private int count = 1;private Boolean flag = False ;//Create a lock L = new Reentrantlock ();//through an existing lock, get the Lock monitor object (Condition)//condition con = l.newcondition ();//through an existing lock, get two sets of monitors , a monitoring producer, a monitoring consumer condition Pro_con = l.newcondition (); Condition Consu_con = l.newcondition ();p ublic void Set (String name) {l.lock (); try {while (flag) {try {pro_con.await ();//Line Process Freeze}catch (Exception e) {//Todo:handle Exception}}this.name = name + count;count++; System.out.println (Thread.CurrentThread (). GetName () + "---producer 5.0----" +this.name); flag = True;//con.signalall ();// Wake all Threads consu_con.signal ();//Wake up the consumer thread without all} catch (Exception e) {//Todo:handle exception}finally{l.unlock ();//Release Lock}} public void Out () {l.lock (), try {while (!flag) {try {consu_con.await ()} catch (Exception e) {//Todo:handle Exception}}sy Stem.out.println (Thread.CurrentThread (). GetName () + "---------Consumer 5.0--------" +this.name); flag = false;// Con.signalall ();p ro_con.signal ();} catch (Exceptione) {//Todo:handle exception}finally{l.unlock ();}}} Class Producer implements Runnable{private Resource R; Producer (Resource r) {THIS.R = R;} public void Run () {while (true) {r.set ("steamed bun");}}} Class Consumer implements Runnable{private Resource R; Consumer (Resource r) {THIS.R = R;} public void Run () {while (true) {R.out ()}}} public class Main {public static void main (string[] args) {Resource r = new Resource (); Producer Pro = new Producer (r); Consumer con = new Consumer (r); Thread t0 = new Thread (PRO); thread T1 = new Thread (PRO); Thread t2 = new Thread (con); thread t3 = new Thread (con); T0.start (); T1.start (); T2.start (); T3.start ();}}
The actual development is such code
class Boundedbuffer {//buffer final lock lock = new Reentrantlock (); Final Condition notfull = Lock.newcondition (); Final Condition notempty = Lock.newcondition (); Final object[] items = new object[100];//Create a large container int putptr, takeptr, Count; public void put (Object x) throws Interruptedexception {Lock.lock (); try {while (count = = items.length) notfull.await (); ITEMS[PUTPTR] = x; if (++putptr = = items.length) putptr = 0; ++count; Notempty.signal (); } finally {Lock.unlock (); }} public Object take () throws Interruptedexception {Lock.lock (); try {while (count = = 0) notempty.await (); Object x = items[takeptr]; if (++takeptr = = items.length) takeptr = 0; --count; Notfull.signal (); return x; } finally {Lock.unlock (); } } }
Java Learning Lesson 26th (Multithreading (vi))-Multi-producer multi-consumer issues