Synchronization of Non-Final Field

Synchronization of non-final field

First of all, I encourage you to really try hard to deal with concurrency issues on a higher level of abstraction, i.e. solving it using classes from java.util.concurrent such as ExecutorServices, Callables, Futures etc.

That being said, there's nothing wrong with synchronizing on a non-final field per se. You just need to keep in mind that if the object reference changes, the same section of code may be run in parallel. I.e., if one thread runs the code in the synchronized block and someone calls setO(...), another thread can run the same synchronized block on the same instance concurrently.

Synchronize on the object which you need exclusive access to (or, better yet, an object dedicated to guarding it).

Java - synchronization on non-final field

You're absolutely right. The moment newObject is exposed to other threads as the new value of someObject, those other threads are now using a completely different mutex, and so can be executing the "mutually exclusive" code concurrently.

A common solution is to just provide a different mutex and synchronize on that:

private final Object someObjectMutex = new Object();

The right way to synchronize on non-final object in Java

You can simplify your locking strategy:

class MyClass {
private final Object lock = new Object();
private Channel channel = null;

public void setChannel() {
// other code can go here

synchronized (lock) {
channel = new Channel();
// setup channel
}

// other code can go here
}

public void unsetChannel() {

// other code can go here

synchronized (lock) {
channel.close();
channel = null;
}

// other code can go here
}

public boolean isSet() {
synchronized (lock) {
if (channel == null) {
return false;
}
return channel.isActive();
}
}
}

In effect, the lock object protects any access to the channel variable.

Edited to show where other code that does not interact with channel might live outside of the locks.

How do I suppress warning Synchronization on a non-final field

For Intellij, put this annotation on the class that has the warnings

@SuppressWarnings("SynchronizeOnNonFinalField")

This lead me to the tag to use for suppression and trial and error lead me to put it on the class instead of on the field or synchronized statement. :-P

When a lock holds a non-final object, can the object's reference still be changed by another thread?

But could a synchronized object's reference also be changed by another thread B while thread A holds the lock for the same object?

If you mean "could another thread change the value of the myTable variable, the answer is "absolutely"... assuming there's a code path that would allow that. It's a private variable, so you should be able to find all the code that can change the value.

Holding a lock just stops another thread from acquiring the same lock. It doesn't have any effect on what code can access which variables, in itself.

As a side-note, it's important to differentiate between an object, a variable, and the value of the variable (which is a reference, not an object). So there's no such thing as a "final object" - only variables (and classes and methods) can be final. Likewise there's no such thing as a "synchronized object", and you can't change an "object's reference" - you can change the value of a variable so that it's a reference to a different object. Making these distinctions clear in your mind may help you when thinking about what's going on here.

Final variable and synchronized block in java

Basically it just means you can't change the value. For instance variables, you have to assign any final variables once (and only once) in the constructor (or with a variable initializer). Synchronization is a pretty orthogonal concept.

The primary reason for making a local variable final is so you can use it in an anonymous inner class... this has nothing to do with being in a synchronized block.

Final variables are useful for immutable classes, admittedly - and immutability makes life easier in a multi-threaded environment - but that's the only relationship between the two that I can think of...

EDIT: Wildwezyr's comment makes sense in terms of not changing the variable on which you are synchronizing. That would be dangerous, for the reasons he's given. Is that what you meant by "variable in synchronized block"?



Related Topics



Leave a reply



Submit