Java multi-thread producer consumer issues < &GT: Using synchronized keyword to address producer consumer issues

Source: Internet
Author: User

Today, read a blog, the Java multi-thread threads of collaboration, in which the author uses the program examples to illustrate the producer and consumer issues, but I and other readers found that the program more than a few times there will be a deadlock, Baidu searched the majority of the sample also has a bug, after careful study found in the problem. And conquer, feel meaningful paste out to share under.

The following is the first to post a bug code, a 4 class. Plate.java:

Package Creatorandconsumer;import java.util.arraylist;import java.util.list;/** * Tray, representing shared resources * @author Martin * */public Class Plate {private list<object> eggs = new arraylist<object> ();/** * Get egg * @return */public Object Getegg () { SYSTEM.OUT.PRINTLN ("Consumers take Eggs"), Object egg = eggs.get (0); eggs.remove (0); return egg;} /** * Add egg * @return */public void Addegg (Object egg) {System.out.println ("producer Raw egg"); Eggs.add (egg);} /** * Get the number of eggs * @return */public int geteggnum () {return eggs.size ();}}
        Consumer class: Consumer2.java

Package Creatorandconsumer;public class Consumer2 implements Runnable {/** * thread resources */private Plate plate;public Consumer2 (P Late plate) {this.plate = plate;} @Overridepublic void Run () {synchronized (plate) {//Assume that the number of eggs is greater than 0 at this time. And so on while (Plate.geteggnum () < 1) {try {///This detail needs to be noted, assuming that the thread enters wait, then the lock on it will be released temporarily. Otherwise, the other thread cannot lock and then wake the thread plate.wait ();} catch (Interruptedexception e) {e.printstacktrace ();}} After awakening. Get the resource lock again. And the condition satisfies can safely take the Egg Plate.getegg ();p late.notify ();}}

Producer class: Creator2.java

Package creatorandconsumer;/** * Producer * *  @author Martin *  */public class Creator2 implements Runnable {/** * thread resource */private Plate plate;public Creator2 (Plate Plate) {this.plate = Plate;} @Overridepublic void Run () {synchronized (plate) {//assuming that the number of eggs at this time is greater than 0, and so on while (Plate.geteggnum () >= 5) {try {///This detail requires attention, assuming The thread enters wait. Then the lock on it will be released temporarily. Otherwise, the other threads cannot be locked. Then wake this thread plate.wait ();} catch (Interruptedexception e) {e.printstacktrace ();}} After awakening, the resource lock is obtained again, and the condition is satisfied to be able to give birth to an egg. Object egg = new Object ();p Late.addegg (egg);p late.notify ();}}

Test class: Tester.java

Package Creatorandconsumer;public class Tester {public static void main (string[] args) {//shared resource plate plate = new plate ();//Plus into producer and consumer for (int i = 0; i <; i + +) {//Bug version new Thread (new CREATOR2 (plate)). Start (); New Thread (New CONSUMER2 (plate)). Start ();//Bug-free version//new Thread (new Creator (plate)). Start ();//new Thread (New Consumer (plate)). Start ();}}

Assuming that you perform multiple executions or change the number of cycles in a test class, you will find that the probability of deadlock is very high. The following analysis has resolved the problem:

This is an explanation for object.wait in the JDK: the current thread must have this object monitor. The thread discards all rights to this monitor and waits until other threads wake up by calling the Notify method, or the Notifyall method notifies the thread waiting on this object's monitor.

It can be seen in one of the following situations: Consumer 1 into the waiting state (at this time the resource lock has been released), assuming that at this time the consumer 2 access to the resource synchronization lock (no one to ensure that consumers 1 into the wait, the next to get the lock must be the producer). Consumer 2 infers that no resources are entering the waiting state. At this time the producer 1 production, and notify the consumer 1, the consumer 1 smooth consumption, and run notify operation, but at this time the consumer 2 is also due to resources and in the waiting state. Thus awakened the consumer 2 (1 of consumers want to awaken other producers). And at this point there is no resource whatsoever. Led to an entire program due to the 2 of consumers trapped in infinite waiting. Formed a deadlock.

After the above analysis. The fundamental reason is that at the same time several consumers or several producers are in a waiting state, causing consumers to wake up or consumers, or the producer wakes or producers. So if we can guarantee that only one consumer is in the wait state at the same time (the same producer), then we can ensure that the consumer wakes up the producer, so that the whole task can go on smoothly. The following is the changed code:

Improved Consumer. java

Package Creatorandconsumer;public class Consumer implements Runnable {/** * thread resource */private Plate plate;/** * producer Lock: Used to lock the same time Only one producer can enter the critical area of production (assuming that two producers enter the critical section at the same time.) It is very likely that one of the producers would have awakened the consumer but awakened the producer) */private static Object consumerlocker = new Object ();p ublic Consumer (Plate Plate) { This.plate = plate;} @Overridepublic void Run () {//must first obtain producer lock talent production synchronized (Consumerlocker) {synchronized (plate) {//assuming that the number of eggs at this time is greater than 0, And so on while (Plate.geteggnum () < 1) {try {///This detail needs to be noted, assuming that the thread enters wait, then the lock on it will be released temporarily. Otherwise, the other thread cannot lock and then wake the thread plate.wait ();} catch (Interruptedexception e) {e.printstacktrace ();}} After wake up, get the resource lock again, and the condition satisfies can be able to take the egg safely Plate.getegg ();p late.notify ();}}}

Improved Creator.java:

Package creatorandconsumer;/** * Producer * *  @author Martin *  */public class Creator implements Runnable {/** * thread resource * /private Plate plate;/** * producer Lock: For locking at the same time only one producer can enter the production critical zone (assuming that two producers enter the critical section at the same time.) It is very likely that one of the producers would have awakened the consumer but awakened the producer) */private static Object creatorlocker = new Object ();p ublic Creator (Plate Plate) { This.plate = plate;} @Overridepublic void Run () {//must first obtain producer lock talent production synchronized (Creatorlocker) {synchronized (plate) {//assuming that the number of eggs at this time is greater than 0, etc. while (Plate.geteggnum () >= 5) {try {//This detail needs attention. Assuming the thread enters wait, the lock on it is temporarily released. Otherwise, the other thread cannot lock and then wake the thread plate.wait ();} catch (Interruptedexception e) {e.printstacktrace ();}} After awakening, the resource lock is obtained again, and the condition is satisfied to be able to give birth to an egg. Object egg = new Object ();p Late.addegg (egg);p late.notify ();}}}

Improvement Note: The improved producer and consumer have added producer lock and Consumer lock respectively. Used to lock only one consumer (producer) into the production critical zone at the same time (assuming that the same time two producers enter the critical section, it is very likely that one of the producers would have awakened the consumer but awakened the producer), which in general is a total of three locks: consumer Lock, producer lock, A lock shared by producers and consumers.

Finally, when writing multithreading, it is important to note that a resource may wake up all the threads that are waiting for the resource, so the consumer thread does not necessarily wake up to the producer thread or the consumer thread.

Java multi-thread producer consumer issues &lt; &GT: Using synchronized keyword to address producer consumer issues

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.