Communication between threads--waiting for a wake-up mechanism

Source: Internet
Author: User

1. Multiple threads operate the same resource, but the action action is different, so there is a security issue
For example:

public class Test {public static void main (string[] args) {Resource r = new Resource ();        Input in = new input (r);        Output out = new output (r);        Thread tin = new thread (in);        Thread tout = new thread (out);        Tin.start ();    Tout.start ();    }}/** * Two Threads Common resource * @author Wangshuang * */class resource{private String name;    Private String sex;    Public String GetName () {return name;    } public void SetName (String name) {this.name = name;    } public String Getsex () {return sex;    public void Setsex (String sex) {this.sex = sex;    }}/** * Memory Resource thread * @author Wangshuang * */class Input implements Runnable {private Resource Resource;    Public Input (Resource Resource) {this.resource=resource;        } @Override public void Run () {int x = 0;              while (true) {synchronized (new Object ()) {if (x==0) {resource.setname ("Zhang San");      Resource.setsex ("male");                    }else{Resource.setname ("Lili");                Resource.setsex ("female female");            } x= (x+1)%2;    }}}}/** * * @author FETCH resource thread * */class Output implements Runnable {private Resource Resource;    Public Output (Resource Resource) {this.resource=resource; } @Override public void Run () {while (true) {synchronized (new Object ()) {SYSTEM.O            Ut.println (Resource.getname () + "..." +resource.getsex ()); }        }    }}

Operation Result:
Tom... Man
Tom... Female female
Tom... Man
Tom... Man
Tom... Female female
Lili ... Man

The cause of the above problem: when the output thread, output is not finished, such as only get to the name Zhang San, the CPU is executed by input, executed two setlili female, when the output again take the thread is sex has become a female, so out

Now the Zhang San ... The phenomenon of women
Added synchronization is also no use, then you should think about the premise of synchronization is not two or more than two threads operating shared resources, is not the same lock object, it is obviously not satisfied

2. Now change the code with the same lock

public class Test {public static void main (string[] args) {Resource r = new Resource ();        Input in = new input (r);        Output out = new output (r);        Thread tin = new thread (in);        Thread tout = new thread (out);        Tin.start ();    Tout.start ();    }}/** * Two Threads Common resource * @author Wangshuang * */class resource{private String name;    Private String sex;    Public String GetName () {return name;    } public void SetName (String name) {this.name = name;    } public String Getsex () {return sex;    public void Setsex (String sex) {this.sex = sex;    }}/** * Memory Resource thread * @author Wangshuang * */class Input implements Runnable {private Resource Resource;    Public Input (Resource Resource) {this.resource=resource;        } @Override public void Run () {int x = 0;                  while (true) {synchronized (Resource) {if (x==0) {resource.setname ("Zhang San");  Resource.setsex ("male");                    }else{Resource.setname ("Lili");                Resource.setsex ("female female");            } x= (x+1)%2;    }}}}/** * * @author FETCH resource thread * */class Output implements Runnable {private Resource Resource;    Public Output (Resource Resource) {this.resource=resource; } @Override public void Run () {while (true) {synchronized (Resource) {SYSTEM.OUT.P            Rintln (Resource.getname () + "..." +resource.getsex ()); }        }    }}

Run results
Tom... Man
Tom... Man
Tom... Man
Tom... Man
Tom... Man
Tom... Man
Tom... Man
Tom... Man
Tom... Man
Tom... Man
Lili ... Female female
Lili ... Female female
Lili ... Female female
Lili ... Female female
Lili ... Female female
Lili ... Female female
Lili ... Female female
Lili ... Female female
Lili ... Female female
Lili ... Female female
Although the Zhang San has been solved ... Women and Lili ... Male problem, but the appearance of the large Zhang San ... Male and large Lili ... Woman, what is this for?

When the tin thread obtains the CPU's execution, executes the SetName and Setsext methods, the CPU execution is still in the tin thread hand, again executes the SetName and Setsext method, covers the previous SetName and Setsex method, after the same .... , then how to implement the save one to take one? There is a wait-for-wake mechanism in multiple threads of Java, with the following code

public class Test1 {public static void main (string[] args) {Resource1 r = new Resource1 ();        INPUT1 input = new INPUT1 (r);        OUTPUT1 output = new OUTPUT1 (r);        New Thread (Input). Start ();        New Thread (Input). Start ();        New Thread (Output). Start ();    New Thread (Output). Start ();    }}/** * Two Threads Common resource * @author Wangshuang * */class resource1{private String name;    Private String sex;    private int count; Private Boolean flag;//adds a token to indicate whether the resource in the resource is empty (the input is not empty after the output represents an empty) public String getoutput () {Sy        Stem.out.println (Thread.CurrentThread (). GetName () + "consumes a" +sex+ "---------------" +name);    return name+ "---" +sex;        } public void SetInput (String name,string sex) {this.name = name+count++;        This.sex = sex;    System.out.println (Thread.CurrentThread (). GetName () + "produced a" +this.sex+ "---" +this.name);    } public boolean Isflag () {return flag;     } public void Setflag (Boolean flag) {   This.flag = Flag;    }}/** * Resource Thread * @author Wangshuang * */class INPUT1 implements Runnable {private Resource1 resource;    Public Input1 (Resource1 Resource) {this.resource=resource;        } @Override public void Run () {int x = 0; while (true) {synchronized (Resource) {if (Resource.isflag ()) {///If flag is true, the resource in the code repository has not been taken away, and the thread should be placed                Discard the CPU execution and wake the other thread to try {resource.wait ();} catch (Interruptedexception e) {e.printstacktrace ();} } try {thread.sleep;} catch (Interruptedexception e) {e.printstacktrace ();}                The thread waiting here is for the convenience of seeing the running result if (x==0) {resource.setinput ("Zhang San", "male");                }else{Resource.setinput ("Lili", "female");                } x= (x+1)%2;                Resource.setflag (TRUE);            Resource.notify (); }}}}/** * * @author resource thread * */class OUTPUT1 implements Runnable {private ResOurce1 resource;    Public Output1 (Resource1 Resource) {this.resource=resource; } @Override public void Run () {while (true) {synchronized (Resource) {if (!resource . Isflag ()) {//If flag is true, the resource in the code repository has not been taken away, at which point the thread should abandon the CPU execution and wake the other thread to try {resource.wait ();} catch (Interrup                Tedexception e) {e.printstacktrace ();} } try {thread.sleep;} catch (Interruptedexception e) {e.printstacktrace ();}                The thread waiting here is to conveniently see the results of the run resource.getoutput ();                Resource.setflag (FALSE);            Resource.notify (); }        }    }}

The results of the operation are as follows:
Thread-0 produced a man---Zhang 30
Thread-3 consumption of a male---------------Zhang 30
Thread-1 produced a man---Zhang 31
Thread-2 consumption of a male---------------Zhang 31
Thread-1 produced a female---lili2
Thread-3 consumed a female---------------lili2
Thread-0 produced a female---lili3
Thread-3 consumed a female---------------Lili3
Thread-0 produced a man---Zhang 34
Thread-3 consumption of a male---------------Zhang 34
Thread-1 produced a man---Zhang 35
Thread-2 consumption of a male---------------Zhang 35
Thread-1 produced a female---lili6
Thread-3 consumed a female---------------lili6
Thread-0 produced a female---lili7
Thread-3 consumed a female---------------lili7
Thread-0 produced a man---Zhang 38
Thread-3 consumption of a male---------------Zhang 38
Thread-0 produced a female---lili9
Thread-3 consumed a female---------------lili9
Thread-0 produced a man---Zhang 310
Thread-2 consumption of a male---------------Zhang 310
Thread-0 produced a female---lili11
Thread-1 produced a man---Zhang 312
Thread-0 produced a man---Zhang 313
Thread-1 produced a female---lili14
Thread-0 produced a female---lili15
Thread-2 consumed a female---------------lili15
Thread-3 consumed a female---------------lili15
Thread-1 produced a man---Zhang 316
Thread-2 consumption of a male---------------Zhang 316
Thread-3 consumption of a male---------------Zhang 316

Thread-1 produced a female---lili17

There is a state of production and consumption of 2, so what is this for?

The first thing to understand is that a thread that does not have the qualification to perform is present in the pool of threads in memory, the order in which the threads are awakened, who first waits, who is awakened first

When the Thread-0 obtains the CPU execution, first to determine whether the resource is empty, is to start production resources, and then determine whether the resource is empty flag flag, set to True, wake up a thread, Thread-0 continue to have the CPU execution, first determine whether the resource is empty, not empty, wait () wait. Then Thread-1 obtains the CPU execution right, first determines whether the resource is empty, is not empty, wait () waits. Then Thread-2 get the CPU execution right, first determine whether the resource is empty, not empty, take out the resource, then flag to false, wake up a thread, and then Thread-3 start execution, first determine whether the resource is empty, is empty, wait () waits, Then Thread-0 obtains the CPU execution right, the last time Thread-0 loses the CPU the execution is through the resource.wait (), then continues to run, the production resource, sets the flag to true, wakes up a thread, Thread-1 obtains the CPU the execution right, The last time Thread-1 lost CPU execution was through resource.wait (), then continued running, production resources, resulting in the production of two resources , set flag to True, wake up a thread, Then Thread-2 get the CPU execution, because the last time the CPU execution is in resource.wait (), so proceed without judging whether the resource is empty, take out the resource, then flag to false, wake up a thread, and then Thread-3 start execution, Since the last loss of CPU execution is in resource.wait (), so continue to execute, do not determine whether the resource is empty, take out the resources, resulting in the consumption of two of the same resource phenomenon
Note that the current thread order is my own imagination of the CPU execution, the CPU execution sequence is random, so all kinds of phenomena can explain the pass, such as the production of two, the consumption of one, the production of a consumption of two, the production of two different, the consumption of 2 of the same (explained above) and so on, So how do we solve this problem?

The reason for this problem is that, without a judgment tag,
Change the place if the resource is empty (Resource.getflag ()) to the while (Resource.getflag ()), so that you can loop the judgment mark, when we run the program again, we will find Thread-0,thread-1, Thread-2,thread-3, all waiting for the state, the cause of this phenomenon, their own according to the Code of execution order to understand it once again, then what to do?

Wake up, do not wake up only one thread, all Wake up OK Notifyall ()

The following code is the last and the simplified code

public class Test {public static void main (string[] args) {Resource r = new Resource ();        Input input = new input (r);        Output output = new output (r);        New Thread (Input). Start ();        New Thread (Input). Start ();        New Thread (Output). Start ();    New Thread (Output). Start ();    }}/** * Two Threads Common resource * @author Wangshuang * */class resource{private String name;    Private String sex;    private int count; Private Boolean flag;//adds a token to indicate whether the resource in the resource is empty (the input represents a non-empty post, and the output represents an out-of-space) public synchronized String  GetOutput () {while (flag) {//If flag is true, the resource in the code repository has not been taken away, at which point the thread should discard the CPU execution and wake the other thread to try {this.wait ();} catch (Interruptedexception e)        {E.printstacktrace ();}        } System.out.println (Thread.CurrentThread (). GetName () + "consumed a" +sex+ "---------------" +name);        Flag=true;        This.notifyall ();    return name+ "---" +sex; synchronized void SetInput (String name,string Sex) {while (!flag) {//if FLAG is false, the resource in the code repository has been removed, at which point the thread should abandon the CPU execution and wake the other thread to try {this.wait ();} catch (Interruptedexception e) {e.printstacktr        Ace ();}        } this.name = name+count++;        This.sex = sex;        System.out.println (Thread.CurrentThread (). GetName () + "produced a" +this.sex+ "---" +this.name);        Flag=false;    This.notifyall ();    }}/** * Memory Resource thread * @author Wangshuang * */class Input implements Runnable {private Resource Resource;    Public Input (Resource Resource) {this.resource=resource;        } @Override public void Run () {int x = 0;                while (true) {if (x==0) {resource.setinput ("Zhang San", "male");                }else{Resource.setinput ("Lili", "female");        } x= (x+1)%2;    }}}/** * * * * * * * * * * * @author resource thread * */class Output implements Runnable {private Resource Resource;    Public Output (Resource Resource) {this.resource=resource;        } @Override public void Run () {while (true) {resource.getoutput (); }    }}

Communication between threads-waiting for a wake-up mechanism

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.