Producer and consumer patterns in multiple threads

Source: Internet
Author: User
Tags stub

When there are multiple threads in a process and it is possible to access the same resource at this point, security issues may occur, so you need to place these resources in a synchronized code block or in a synchronization method before you access them, by synchronized keyword declarations, Only one thread can exist at this time, and the thread cannot manipulate the shared resource until it acquires the corresponding lock, and then the other thread can acquire the lock and then manipulate the shared resource.

These are some of the basic operations of multithreading when working with the same data, so if multiple threads are working on the same resource at this time, different functions are implemented. For example, there will be security checks at the train station or subway station, and passengers ' baggage goes from side to side, and the producer and consumer models are similar.

Now to analyze, if there is an item package to go into security to detect and then come out, so there are two kinds of operations, create a resource class, create two methods a control to enter, a control output.

class resource{private String name;
    Private Boolean flag = false;
        Public synchronized void Set (String name) {//When flag is true, enter thread wait, do not set value operation,///When flag is false, set value, and flag reverse, wake output thread
            if (flag) try {this.wait ();
            catch (Interruptedexception e) {//TODO automatically generated catch block E.printstacktrace ();
        } this.name = name;
        System.out.println (Thread.CurrentThread (). GetName () + "-->in" +this.name);
        Flag =true;
    This.notify ();
            Public synchronized void out () {if (!flag) {try {this.wait ();
            catch (Interruptedexception e) {//TODO automatically generated catch block E.printstacktrace ();
        } System.out.println (Thread.CurrentThread (). GetName () + "-->out" +this.name);
        Flag = false;
    This.notify (); }
}

So what is the role of the flag here, first of all to understand the thread waiting for the wake mechanism, because only input a package to output one, so two lines thread alternate execution, but in the case of the same lock, the thread will rob CPU execution rights, and then there will be uncertainty, So it may be inconsistent with the actual situation, so to be in a thread a execution, you should ensure that another line B is in the waiting state, a after the completion of the wake thread B and then wait, and B also imitate this behavior, which avoids the logical error occurred. Then look at flag, here. If the current thread waits for a condition that does not match the value passed in, the operation in the method is performed, otherwise it enters the waiting state, wakes another thread when the normal operation is completed, and reverses the flag, making the alternating work working normally.

Here is the complete program:

Class resource{private String name;
    Private Boolean flag = false;
        Public synchronized void Set (String name) {//When flag is true, enter thread wait, do not set value operation,///When flag is false, set value, and flag reverse, wake output thread
            if (flag) try {this.wait ();
            catch (Interruptedexception e) {//TODO automatically generated catch block E.printstacktrace ();
        } this.name = name;
        System.out.println (Thread.CurrentThread (). GetName () + "-->in" +this.name);
        Flag =true;
    This.notify ();
            Public synchronized void out () {if (!flag) {try {this.wait ();
            catch (Interruptedexception e) {//TODO automatically generated catch block E.printstacktrace ();
        } System.out.println (Thread.CurrentThread (). GetName () + "-->out" +this.name);
        Flag = false;
    This.notify ();
 } class Producer implements runnable{Resource Res;   Public Producer (Resource res) {this.res = res; @Override public void Run () {//TODO automatically generated method stub while (true) {Res.set ("\ T" + "Package
        ");
    }} class Consumer implements runnable{Resource res = new Resource ();
    Public Consumer (Resource res) {this.res = res;
        @Override public void Run () {//TODO automatically generated method stub while (true) {res.out ();
        }} public class Prodandcons {public static void main (string[] args) {Resource res = new Resource ();
        Producer p = new Producer (res);
        Consumer C = new Consumer (res);
        Create two threads to test thread T1 = new Thread (p);
        Thread t2 = new Thread (c);
        T1.start ();
        T2.start (); }
    }

You can see the input and output alternating, which is the effect of two threads, if there are more threads.
Create two more threads in the Main method

...
thread T1 = new Thread (p);
Thread t2 = new Thread (p);
thread t3 = new thread (c);
thread T4 = new thread (c);

T1.start ();
T2.start ();
T3.start ();
T4.start ();
...


You can see that when there are more than two threads executing, there will be a two or more occurrences of the phenomenon, what is the reason that can be analyzed, for example, there are four threads A,b,c,d,a and b control input, C and D control output. If flag is false after a program has been in place for some time, an input operation is executed by a and B, assuming that a executes the input and then reverses the flag and wakes the thread, at which point a waits because the flag condition is met, and the b,c,d is qualified for execution, and the B assumes the execution right, Because flag is true, B also waits. Then execute the c,c to perform the output operation, reverses the flag, then wakes up a wait and the longest time a, and C itself loses the execution qualification, so does D, and then A has to execute the input and then wake up with thread B, and B is already waiting so there is no need to judge the direct execution of the input operation, This results in a two-input-once output, and of course there are other results to continue the analysis.

So how do you solve this problem? Because a thread may be awakened at some point, it omits a step of judgment, causing a security problem, so if you change the if to a while, the thread is judged more than once.

This solves the logic problem of inconsistent input and output, but the execution of the program will stop automatically, because when C and D are waiting, thread a wakes up the waiting B before waiting, but in the while loop it is again judged that a will turn the flag back to an executable state, and B is satisfied. As a result, B loses its eligibility to perform, and the program stops when no threads are executing. So the solution is to wake up all the waiting threads every time the thread finishes, calling the Notifyall method.

This problem has been solved, reached the beginning of the baggage through security screening effect, but also the so-called producer consumers.

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.