Should getters and setters synchronize?

private double value; public synchronized void setValue(double value) { this.value = value; } public double getValue() { return this.value; } 

In the above example, is there any point for getter synchronization?

+45
java synchronized
Jul 12 '12 at 19:50
source share
4 answers

I think it's best to call Java Concurrency in practice here:

A common mistake is that synchronization should only be used when writing to shared variables; this is simply not true.

For each mutable state variable, access to which can be more than one thread, all calls to this variable must be performed with the same locked lock. In this case, we say that the variable is protected by that lock.

In the absence of synchronization, the compiler, processor, and runtime can do some completely strange things in the order of operations. Attempts to speculate on the order in which memory actions “should” occur in insuffl-synchronized multi-threaded programs will almost certainly be incorrect.

Usually you do not need to be so careful with primitives, so if it is int or boolean , perhaps this is:

When a stream reads a variable without synchronization, it can see but at least it sees the value that some stream actually placed there, and not some random value.

This, however, is not true for 64-bit operations, for example, on long or double , if they are not declared volatile :

The Java memory model requires fetching and storing operations to be atomic, but for non-volatile long and double variables, the JVM is allowed to process 64-bit read or write as two separate 32-bit operations. If reading and writing occur in different therefore, it is possible to read non-volatile length and receive return 32 bits of one value and low 32 bits of another.

Thus, even if you do not need obsolete values, it is unsafe to use common modified long and double variables in multi-threaded programs unless they are declared unstable or protected by a lock.

+64
Jul 12 2018-12-12T00:
source share

Let me show you an example, which is a legal way for JIT to compile your code. You write:

 while (myBean.getValue() > 1.0) { // perform some action Thread.sleep(1); } 

JIT compiles:

 if (myBean.getValue() > 1.0) while (true) { // perform some action Thread.sleep(1); } 

In a few different scenarios, even a Java compiler could come to terms with a similar bytecode (it would eliminate the possibility of dynamically sending to another getValue ). This is a training example of a climb.

Why is this legal? The compiler has the right to assume that the result of myBean.getValue() cannot change when executing the code above. Without synchronized allowed to ignore any actions of other threads.

+12
Jul 12 2018-12-12T00:
source share

The reason here is to protect against any other thread updating the value when the stream is reading, and thus avoid doing anything with an outdated value.

Here, the get method will get an internal lock on "this", and thus, any other thread that might try to set / update using the setter method will have to wait to get a lock on "this" in order to introduce the setter method, which is already received Stream execution in progress.

That is why it is recommended to adhere to the practice of using the same lock when performing any operation in a mutable state.

Creating field volatile will work here since there are no compound statements.




It is important to note that synchronized methods use the built-in lock "this". So, get and establish that both are synchronized, means that any thread entering the method will have to block it.




When performing non-atomic 64-bit operations, special care should be taken. Excerpts from Java Concurrency In practice, it may help here to understand the situation -

"The Java memory model requires that the retrieval and storage operations be atomic, but for non-volatile long and double variables, the JVM is allowed to treat 64-bit read or write as two separate 32 bits. If the read and write occur in different streams, so long-term long-term read information and return high 32 bits of one value and the lower 32 bits of another.Thus, even if you do not need obsolete values, it is unsafe to use common modified long and double variables in multi-threaded ogrammah, if they are not fragile or protected lock. "

+1
Apr 22 '14 at 7:37
source share

This code may look awful to someone, but it works very well.

  private Double value; public void setValue(Double value){ updateValue(value, true); } public Double getValue(){ return updateValue(value, false); } private double updateValue(Double value,boolean set){ synchronized(MyClass.class){ if(set) this.value = value; return value; } } 
-one
May 23 '17 at 9:05 a.m.
source share



All Articles