End Field Thread Safety

Let's say I have a JavaBean user that is updated from another thread, for example:

public class A { private final User user; public A(User user) { this.user = user; } public void aMethod() { Thread thread = new Thread(new Runnable() { @Override public void run() { ...a long running task.. user.setSomething(something); } }); t.start(); t.join(); } public void anotherMethod() { GUIHandler.showOnGuiSomehow(user); } } 

Is this code safe? I mean, when the thread that instantiated A and called A.aMethod reads the user’s fields, does it see the user in a new state? How to do this in a suitable streaming mode?

Please note that I cannot change the user class, and I do not know if it is really thread safe.

+5
source share
6 answers

Is this code safe? ... does it see the user in a new state?

Not especially - the fact that user is final in your code has practically no effect on thread safety, except that it cannot be replaced.

The bit that needs to change is the instance variable set by setSomething . It should be marked as volatile .

 class User { // Marked `volatile` to ensure all writes are visible to other threads. volatile String something; public void setSomething(String something) { this.something = something; } } 

If, however (as you assume), you do not have access to the user class, you must perform synchronization, which creates a memory barrier. In its simplest form, you can combine your user access with synchronized access.

 synchronized (user) { user.setSomething(something); } 

Added: - It turns out (see here ) that this can be done as follows:

 volatile int barrier = 0; ... user.setSomething(something); // Forces **all** cached variable to be flushed. barrier += 1; 
+4
source

The final marking field means that the link cannot be changed. This does not mean anything about the safety of a User class thread. If methods of this class that access the fields are synchronized (or use a different synchronization technique), they are thread safe. Otherwise, this is not so.

+4
source

final makes the link undefinable, but if the link points to a mutable class, you can still change the state inside this object, which causes unsafe behavior.

Your code is only thread safe if the User class is immutable, Ie all user properties cannot be changed outside the object, all links in the class point to another immutable class.

If this is not the case, then you need to correctly synchronize its methods to make it thread safe.

0
source

Please note that I cannot change the user class, and I do not know if it is really thread safe.

You must synchronize your access when accessing the User object. For example, you can use the User object for synchronization, so just wrap each access to the user object with something like:

 synchronized(user) { // access some method of the user object } 

It is assumed that the user object will only be available in your threads asynchronously. Also keep synchronized blocks short.

You can also create a thread-safe wrapper around a user object. I would suggest that if you have many different calls, the code becomes cleaner and it is better to read this way.

Good luck

0
source

As for streaming, final fields are guaranteed to be consistent in the case of constructor escape code , since JSR-133 is about the memory mechanism:

Values ​​for the final fields of the object are set in its constructor. Assuming that the object is built “correctly”, as soon as the object the constructed values ​​assigned to the final fields in the constructor will be visible to all other threads without synchronization. In addition, the visible values ​​for any other object or array referenced by these trailing fields will be at least the same as the last fields. What does this mean for an object? built correctly? It simply means that no reference to an object being built is allowed to "escape" during construction. (See Safe construction methods for examples.) In other words, do not put a link to an object that is being built anywhere where another thread could see it; do not assign it to a static field, do not register it as a listener with any other object, and therefore on. These tasks should be performed after completion of the constructor, and not in the constructor.

However, nothing provides automatic protection of threads from any finite fields in the remaining resource of the object (this means that after the constructor of the shell class is executed). . Indeed, immutability in Java is a pure incorrect expression:

Now, in general terms, immutability means "does not change." Invariance does not mean that it "does not change" in Java. This means that "there is a transit reachable from a finite field, it has not changed since the final field was set, and the reference to the object containing the final field did not leave the constructor."

0
source

Yes, it is safe. Cm

The Java Language Specification (Java 8) Chapter 17.4.4 :

The final action in thread T1 is synchronized with any action in another thread T2 that detects that T1 is complete.

T2 can accomplish this by calling T1.isAlive () or T1.join ().

Put this together with 17.4.5. It happens before the order :

Two actions can be ordered using an occur-to relationship. If one action occurs - in front of another, then the first is visible and ordered before the second. [..] If the action x is synchronized with the next action y, then we also have hb (x, y).

So, after calling t.join(); You will see updated changes in your code. Since "the thread that created the instance and called A.aMethod", it is impossible to read the value after calling aMethod and before calling t.join (because it is busy using the aMethod method), this is safe.

0
source

Source: https://habr.com/ru/post/945674/


All Articles