简体   繁体   中英

java threading lock variable properly

Thread A does:

class A{
    public String value;
    public void methodA(String value){ //lets say value="test"
        this.value=value;
        //some code
        // Thread B interrupts
        System.out.println(value); // prints "haha" but I want it to be "test"
    }
}

Thread B does:

class B{
    public void methodB(){
        a.setValue("haha");  
    }
}

methodB and methodA are some kinds of listener methods, which are executed in separate Threads.

How can I make sure that value does not change, as long as methodA has not finished? But I want also that "haha" is assigned to value afterwards. So I want B to wait till A has finished methodA and then assign "haha" to value.

The easiest way is to use 'synchronized' keyword on method that change the value of a field.

For example we have class that stores the data:

public class Data {
   String value = "";
   public synchronized void setValue(String val) {
      this.value = val;
      System.out.println(val);
   }
}

And then Threads only use this method to update the value. Only one thread at the time can execute this method (no interrupts).

If you want to propagate this on two methods (like I suppose is the case). You can use two options. Or use synchronized on both methods or use external lock object.

If you want to be sure, that for example thread A has to be first to execute, you can use CountDownLatch object, which will stop other threads until thread A won't decrement the latch.

There are many ways to handle synchronization. You should be more precise to what you want to achieve and what kind of scenario you want to handle. Like for example - Is a.setValue("haha") a method from class A?

I would also recommend to look at documentation about concurrency https://docs.oracle.com/javase/tutorial/essential/concurrency/ .

If you just want methodA() to complete before methodB() is called, then you should call both methods from the same thread. In general, if you want your program to do certain things in a certain order, the best way to accomplish it is to do all of the things in a single thread.

On the other hand, you might want both threads to work in parallel most of the time, but there might be one particular point that you don't want thread B to pass until thread A gets there. The Java standard library provides a variety of different synchronization objects that you could use. Eg, java.util.concurrent.CountDownLatch .

Initialization:

CountDownLatch countDownLatch=new CountDownLatch(1);
threadA.start();
threadB.start();

Thread A:

doSomeStuff();
methodA();
countDownLatch.countDown();
doSomeMoreStuff();

ThreadB:

doSomeOtherStuff();
countDownLatch.await();
methodB();
doSomeMoreOtherStuff();

The doSomeStuff() and doSomeOtherStuff() calls could happen concurrently, and the doSomeMoreStuff() and doSomeMoreOtherStuff() calls could happen concurrently, but the methodA() and methodB() would be serialized in this case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM