Reputation: 3532
In this oracle example of intrinsic locks and many more, the monitor object is never declared as volatile, final or nor it has any distinction from any other regular object
public class MsLunch { private long c1 = 0; private long c2 = 0; private Object lock1 = new Object(); private Object lock2 = new Object(); public void inc1() { synchronized(lock1) { c1++; } } public void inc2() { synchronized(lock2) { c2++; } } }
There are plenty of questions that debate volatile versus synchronization blocks
and immutable objects
As a side note, I understand this subtle difference between declaring an object final versus immutability why-can-final-object-be-modified and why declaring the lock object as final would not make it immutable.
However, we have the famous pattern of the singleton class lazy initialization where the use of the volatile
variables is essential.
public class SingletonDemo { private static volatile SingletonDemo instance; private SingletonDemo() { } public static SingletonDemo getInstance() { if (instance == null ) { synchronized (SingletonDemo.class) { if (instance == null) { instance = new SingletonDemo(); } } } return instance; } }
which in the above code example uses the Class object as lock.
Since for an object which is accessed by multiple threads you need to use some mechanism as above to ensure atomic access, why is that for intrinsic lock object there is no need for any special treatment?
Upvotes: 1
Views: 355
Reputation: 93668
It probably should be final. But final isn't anything really special- its only required in one special case (referencing a variable declared inside a function into an anonymous class). Any other case final is simply a reminder for the programmer to not overwrite the variable- you can remove every other use of the word final in your program and it will work perfectly. You're right, a programmer could assign to it and then cause problems. But if he doesn't, there's no issue. So go ahead and use final when you create one, but it isn't necessary for the program to compile.
As for static- depends on the usecase. Do you want to monitor all instances of a class, or each instance independently? In the first case, you use static in the second case you don't.
Volatile isn't needed because the object isn't actually being changed by the multiple threads. Its being synchronized on. This is completely different, and an older part of the Java language than volatile. There's no need to make the variable volatile as you won't be altering it, and the internal data structures used to monitor on an object already know they need to be thread safe (and in a stronger manner than volatile promises).
Upvotes: 0
Reputation: 310985
In this oracle example of intrinsic locks and many more, the monitor object is never declared as volatile, final or nor it has any distinction from any other regular object.
That's not true. See below.
Since for an object which is accessed by multiple threads you need to use some mechanism as above to ensure atomic access, why is that for intrinsic lock object there is no need for any special treatment?
It does have special treatment. It is synchronised on.
Upvotes: -1
Reputation: 11030
These locks don't need special treatment because the MsLunch
object itself needs to be published before it can be seen by any additional threads.
public class MyMain {
public static void main(String... args) {
MsLunch lunch = new MsLunch();
// ...
This is thread safe because local variables ("lunch
") are not visible to more than one thread.
Next the class below makes the local reference visible to all threads in the system. When that happens we need to use volatile
. The volatile
keyword effectively creates a memory barrier that publish the object safely. This includes all writes made before the assignement including writes made internally when constructing the object.
C.f. Safe Publication
public class MyMain {
public static volatile MsLunch publicLunch;
public static void main(String... args) {
MsLunch lunch = new MsLunch();
publicLunch = lunch;
//...
}
}
Upvotes: 1