synchronization on single statement?

2019-07-22 18:15发布

问题:

if I have a getter method that has only one statement like this

public class NumberClass{
    int number;

    public int getNumber() {
        return number;
    }
    ...
}

and multiple threads access this method, do I have to synchronize this method or it is not necessary since it has only one statement??

回答1:

I have to synchronize this [get] method or it is not necessary since it has only one statement??

It has nothing to do with 1 or more statements. It depends on whether or not the value has been updated in another thread and if you want all of the threads to see a consistent value.

If the number field was updated in thread1, then thread2 may get either the original value or the new value depending on how the update was synchronized. To have the value published appropriately both the set and get methods need to synchronized.

If you are just trying to share an int value then marking the number field as being volatile would work or using an AtomicInteger to share the value between multiple threads reliably may be more appropriate.

private volatile int number;

or use:

private AtomicInteger number = new AtomicInteger();


回答2:

Yes, it may be a good idea to synchronize that statement. The reason is that each thread is, according to spec, allowed to cache its own version of the variable. To se it demonstrated, have a look at this answer.

Other options are to

  • Make the variable volatile:

    volatile int number;
    
  • or to use AtomicInteger from the java.util.concurrent package:

    AtomicInteger number;
    

As a side-note: If number had been of type long, not even a read of the variable would have been atomic (one thread could rewrite the value of the variable in the middle of a read). See Chapter 17.7: Non-atomic Treatment of double and long of the Java Language Specification.



回答3:

You need a memory barrier, or other threads are not guaranteed to see the "correct" value (meaning, any value that is explicitly assigned to number).

To fix this, declare number as a final or volatile member, or access it from a synchronized block.

The number of statements, contrary to some other answers, is a consideration. You do not need atomicity (because it's a single statement), so using synchronized is probably overkill. If the value changes, use volatile, and if it doesn't, use final. If you had multiple statements that needed to appear as acting atomically, synchronized would be the only option.