Synchronized methods with independent shared variables - java

I recently asked about if synchronized methods in Java shared the same lock key. The answer was yes. But the next thought I had was that this pattern is very restrictive and can cause unnecessary delays. For example suppose we have 2 synchronized methods and each of them process different and independent shared variables. What's the point of locking both methods at the same time if the processing of one variable does not affects the other? Is there a way to deal with this situation?

Suppose you have this class:
class C {
public synchronized void foo(...) { ... }
public synchronized void bar(...) { ... }
...
}
And suppose you have:
final C c_0 = new C(...);
final C c_1 = new C(...);
The fact that foo() and bar() both are synchronized does not prevent one thread from calling c_0.foo(...) while another thread simultaneously calls c_1.bar(...). In fact, it does not even prevent one thread from calling c_0.foo(...) while another thread calls c_1.foo(...).
A so-called "synchronized method"
synchronized void foo(...) { ... }
Really is just syntactic sugar for this:
void foo( ... ) {
synchronized(this) {
...
}
}
So, if one thread calls c_0.foo() it's "synchronizing" on the c_0 instance, and if another thread calls c_1.foo(), that thread is synchronizing on the c_1 instance--a different instance.
The synchronized keyword on the foo and bar methods only matters if two different threads both try to operate on the same instance at the same time.

Related

If you have a lock on an object, do you have a lock on all its methods?

Say we have a object foo:
class Foo(){
public synchronized void instanceMethod(){}
}
var foo = new Foo();
if I have a lock on foo:
synchronized(foo){
foo.instanceMethod();
}
do I also have a lock on the instanceMethod() call? Another way of asking the question - if I have a lock on foo, can another thread call foo.instanceMethod() (simultaneously)?
if I have a lock on foo, can another thread call foo.instanceMethod()?
They can call it, but the call will wait until execution leaves your block synchronized on foo, because instanceMethod is synchronized. Declaring an instance method synchronized is roughly the same as putting its entire body in a block synchronized on this.
If instanceMethod weren't synchronized, then of course the call wouldn't wait.
Note, though, that the synchronized block you've shown is unnecessary:
synchronized(foo){ // <==== Unnecessary
foo.instanceMethod();
}
Because instanceMethod is synchronized, that can just be:
foo.instanceMethod();
...unless there's something else in the block as well.
class Foo {
public synchronized void a() { //Do something }
public void b() {
synchronized(this) { // Do something }
}
public void c() { // Do something }
}
Then:
Foo foo = new Foo();
foo.a();
foo.b();
synchronized(foo) { foo.c(); }
All the 3 methods are all pretty much equivalent in terms of synchronization.
There is no such thing as "locking" a method. Locking is done only on objects. Marking a method synchronized simply makes it lock the instance (or its class object for static method).
When you access a method on a locked object, the execution would be blocked as the thread fails to retrieve the monitor for the specified object - that is even before the method has been called. So foo.a() would be blocked when it is getting the foo.
Adding on...
I suddenly remembered something. If you have thread A calling foo.a() and it is taking a very long time to complete, and at that time another thread calls foo.c(), then foo.c() will still be blocked until foo.a() completes.

Why do we write Synchronized(ClassName.class)

I have a question in singleton pattern.
In singleton pattern we write
synchronized(ClassName.class){
// other code goes here
}
What is the purpose of writing ClassName.class?
In a member method (non-static) you have two choices of which monitor (lock) to use: "this" and "my class's single static lock".
If your purpose is to coordinate a lock on the object instance, use "this":
...
synchronized (this) {
// do critical code
}
or
public synchronized void doSomething() {
...
}
However, if you are trying to have safe operations including either:
static methods
static members of your class
Then it is critical to grab a class-wide-lock. There are 2 ways to synchronize on the static lock:
...
synchornized(ClassName.class) {
// do class wide critical code
}
or
public static synchronized void doSomeStaticThing() {
...
}
VERY IMPORTANTLY, the following 2 methods DO NOT coordinate on the same lock:
public synchronized void doMemberSomething() {
...
}
and
public static synchronized void doStaticSomething() {
...
}
Each class (for example Foo) has a corresponding, unique instance of java.lang.Class<Foo>. Foo.class is a literal of type Class<Foo> that allows getting a reference to this unique instance. And using
synchronized(Foo.class)
allows synchronizing on this object.
The object that you pass into the synchronized block is known as a monitor. Since the object that represents the class className.class is guaranteed to only exist once in the JVM it means that only one thread can enter that synchronized block.
It is used within the singleton pattern to ensure that a single instance exists in the JVM.

Synchronization with copied references for compound statements in Java

Let's say we have an object whose methods/fields are synchronized on "this". This question is actually about "this" as I think I have a hard time what "this" reference means.
So our object is:
class A {
private Field a;
private Field b;
public synchronized void doSomething() {
//something with a
}
public synchronized void somethingElse() {
//do something as with b
}
}
Then we have another object or method that takes A objects and do work on a and b via doSomething and somethingElse methods. So I need to keep the state consistent while I process A objects, hence I synchronize. Let's say those A objects are values of a Map. Then I am iterating over the values and do the things that I do. So the question is, is it thread-safe to do it in the following way:
for(A aObject : map.values()) {
synchronized(aObject) {
aObject.doSomething();
aObject.somethingElse();
}
}
If the "this" reference is the same reference as aObject, I think I shouldn't be in trouble. But what if I do it like this:
for(A aObject : map.values()) {
A anotherReference = aObject;
synchronized(anotherReference) {
anotherReference.doSomething();
anotherReference.somethingElse();
}
}
Is it still thread-safe? I mean can I synchronize on a local copy of a lock reference?
Note: this is an oversimplification of something I need to do in my code.
The synchronisation monitor belongs to the object that is referenced, not the reference, so your two for loops are equivalent, they both synchronise on the same object.
Now a synchronized method
public synchronized void foo() {
// do stuff
}
is exactly equivalent to
public void foo() {
synchronized(this) {
// do stuff
}
}
so in the loop
for(A aObject : map.values()) {
synchronized(aObject) {
aObject.doSomething();
aObject.somethingElse();
}
}
the synchronized block is locking the same monitor as the doSomething() and doSomethingElse() methods use themselves. What you gain from the synchronized block is that no other thread can sneak in and call either of those methods on the same A instance in between these two calls.
you seems to be confused about what references are, so i would go read up on them. when you use a synchronized block, you are not synchronizing on the reference itself, but on the object instance to which the reference refers.
for example:
Object a = new Object();
Object b = a;
synchronized(a) { ... }
synchronized(b) { ... }
these two synchronized blocks are synchronizing on the same Object instance because a and b refer to the same Object instance.
Following from that, a synchronized method is the same as synchronizing on the this reference.
for example:
public class A {
public synchronized void doStomething() { ... }
public void doSomethingElse() { synchronized(this) { ... } }
}
both of these methods are synchronizing on the same Object instance (the current instance), using the self reference known as this. you can rewrite either example as the other example and they are equivalent.
So, returning to your original example, i hope you will understand that when you synchronized on an Object instance externally through a reference (as my first example), it is doing the same thing as an Object synchronizing internally on itself.
To wrap, your last example is a common idiom when working on synchronized collections as it enables the caller to ensure that 2 operations are performed atomically with respect to the Collection.
for example:
// this will result in a List where all methods are internally synchronized
List<Object> syncList = Collections.synchronizedList(new ArrayList<Object>());
// i can safely perform an atomic operation on the List using this pattern
synchronized(syncList) {
if(syncList.isEmpty()) { // <- synchronized method call
syncList.add(...); // <- synchronized method call
}
}
In Java we have two basic synchronization idioms: synchronized methods and synchronized statements.
When you use the first idiom (synchronized methods) as in the following code:
public class SynchronizedCounter {
private int c = 0;
public synchronized void increment() {
c++;
}
public synchronized void decrement() {
c--;
}
public synchronized int value() {
return c;
}
}
You have two main effects:
1) it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
2) when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
Another way to create synchronized code is with synchronized statements. Unlike synchronized methods, synchronized statements must specify the object that provides the intrinsic lock:
public void addName(String name) {
synchronized(this) {
lastName = name;
nameCount++;
}
nameList.add(name);
}
In your code you're using both of these idioms. Then, your first for loop doesn't need the synchronized(aObject) because your class methods are already synchronized methods.
source: http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
But let's say your class methods weren't synchronized. Your second code example:
for(A aObject : map.values()) {
A anotherReference = aObject;
synchronized(anotherReference) {
anotherReference.doSomething();
anotherReference.somethingElse();
}
}
Still works, because in Java every object has an intrinsic lock associated with it. When you call synchronized(Object o) you're acquiring the lock associated with the Object: anotherReference, that in your case is the aObject.
Let's think about two Thread: T1 and T2.
If T1 call this for loop before T2, it acquires the intrinsic lock associated with the aObject and T2 won't able to do the same till T1 will end both methods: doSomenthing() and somethinElse().

difference between synchronizing a static method and a non static method

What is the difference between synchronizing a static method and a non static method in java?Can anybody please explain with an example. Also is there any difference in synchronizing a method and synchronizing a block of code?
I will try and add an example to make this extra clear.
As has been mentioned, synchronized in Java is an implementation of the Monitor concept. When you mark a block of code as synchronized you use an object as a parameter. When an executing thread comes to such a block of code, it has to first wait until there is no other executing thread in a synchronized block on that same object.
Object a = new Object();
Object b = new Object();
...
synchronized(a){
doStuff();
}
...
synchronized(b){
doSomeStuff();
}
...
synchronized(a){
doOtherStuff();
}
In the above example, a thread running doOtherStuff() would block another thread from entering the block of code protecting doStuff(). However, a thread could enter the block around doSomeStuff() without a problem as that is synchronized on Object b, not Object a.
When you use the synchronized modifier on an instance method (a non-static method), it is very similar to having a synchronized block with "this" as the argument. So in the following example, methodA() and methodB() will act the same way:
public synchronized void methodA() {
doStuff();
}
...
public void methodB() {
synchronized(this) {
doStuff();
}
}
Note that if you have a methodC() in that class which is not synchronized and does not have a synchronized block, nothing will stop a thread from entering that method and careless programming could let that thread access non-safe code in the object.
If you have a static method with the synchronized modifier, it is practically the same thing as having a synchronized block with ClassName.class as the argument (if you have an object of that class, ClassName cn = new ClassName();, you can access that object with Class c = cn.getClass();)
class ClassName {
public void static synchronized staticMethodA() {
doStaticStuff();
}
public static void staticMethodB() {
synchronized(ClassName.class) {
doStaticStuff();
}
}
public void nonStaticMethodC() {
synchronized(this.getClass()) {
doStuff();
}
}
public static void unSafeStaticMethodD() {
doStaticStuff();
}
}
So in the above example, staticMethodA() and staticMethodB() act the same way. An executing thread will also be blocked from accessing the code block in nonStaticMethodC() as it is synchronizing on the same object.
However, it is important to know that nothing will stop an executing thread from accessing unSafeStaticMethodD(). Even if we say that a static method "synchronizes on the Class object", it does not mean that it synchronizes all accesses to methods in that class. It simply means that it uses the Class object to synchronize on. Non-safe access is still possible.
In short if you synchronize on a static method you will synchronize on the class (object) and not on an instance (object). That means while execution of a static method the whole class is blocked. So other static synchronized methods are also blocked.
Synchronization in Java is basically an implementation of monitors. When synchronizing a non static method, the monitor belongs to the instance. When synchronizing on a static method, the monitor belongs to the class. Synchronizing a block of code is the same idea, but the monitor belongs to the specified object. If you can get away with it, synchronized blocks are preferable because they minimize the time each thread spends in the critical section
There is virtually no difference between synchronizing a block and synchronizing a method. Basically:
void synchronized m() {...}
is the same as
void m() { synchronized(this) {...} }
By comparison a static synchronized method is the same as:
static void m() { synchronized(MyClass.class) {...} }
Dude, just a hint. Not related to your question:
If any do*Stuff() methods does either
this.a= /*yet another*/ new Object();
or
this.b= /*yet another*/ new Object();
then you are screwed. Because the lock is inside the value, not inside the reference. See Java synchronized references
From javadoc https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
when a static synchronized method is invoked, since a static method is associated with a class, not an object. In this case, the thread acquires the intrinsic lock for the Class object associated with the class. Thus access to class's static fields is controlled by a lock that's distinct from the lock for any instance of the class.
public static synchronized void getInstance(){}
When we acquire a lock on any class, we actually acquire a lock on "Class" class instance which is only one for all instances of class.
public synchronized void getInstance(){}
we can create multiple object's of a class and each object will have one lock associated with it.

Concurrency in Java: synchronized static methods

I want to understand how locking is done on static methods in Java.
let's say I have the following class:
class Foo {
private static int bar = 0;
public static synchronized void inc() { bar++; }
public synchronized int get() { return bar; }
It's my understanding that when I call f.get(), the thread acquires the lock on the object f and when I do Foo.inc() the thread acquires the lock on the class Foo.
My question is how are the two calls synchronized in respect to each other?
Is calling a static method also acquires a lock on all instantiations, or the other way around (which seems more reasonable)?
EDIT:
My question isn't exactly how static synchronized works, but how does static and non-static methods are synchronized with each other.
i.e., I don't want two threads to simultaneously call both f.get() and Foo.inc(), but these methods acquire different locks. My question is how is this preventable and is it prevented in the above code.
Static and instance synchronized methods are not related to each other, therefore you need to apply some additional synchronization between them, like this:
class Foo {
private static int bar = 0;
public static synchronized void inc() { bar++; }
public synchronized int get() {
synchronized (Foo.class) { // Synchronizes with static synchronized methods
return bar;
}
}
}
(though in this case leaving synchronized on get() doesn't make sense, since it doesn't do anything that requires synchronization on instance).
Beware of deadlocks - since this code aquires multiple locks, it should do it in consistent order, i.e. other synchronized static methods shouldn't try to acquire instance locks.
Also note that this particular task can be solved without synchronization at all, using atomic fields:
class Foo {
private static AtomicInteger bar = new AtomicInteger(0);
public static void inc() { bar.getAndIncrement(); }
public int get() { return bar.get(); }
}
A synchronized static method is effectively equivalent to:
public static void foo() {
synchronized (ClassName.class) {
// Body
}
}
In other words, it locks on the Class object associated with the class declaring the method.
From section 8.4.3.6 of the JLS:
A synchronized method acquires a monitor (ยง17.1) before it executes. For a class (static) method, the monitor associated with the Class object for the method's class is used. For an instance method, the monitor associated with this (the object for which the method was invoked) is used.
If you read http://download.oracle.com/javase/tutorial/essential/concurrency/locksync.html.
It will tell you:
You might wonder what happens when a
static synchronized method is invoked,
since a static method is associated
with a class, not an object. In this
case, the thread acquires the
intrinsic lock for the Class object
associated with the class. Thus access
to class's static fields is controlled
by a lock that's distinct from the
lock for any instance of the class.
which tells you all you need to know.
Neither, the non-static synchronized call does not acquire a lock on the class itself. (And the static synchronized block does not lock any object instantiated from that class.)
In other words the calls f.get() (locks f) and Foo.inc() (locks the class Foo) can run concurrently. They are not "synchronized".
You could use a different pattern (singleton), or make all the methods static.
Static locks are attached to the class definition and thus is shared between all instances of that class.
Synchronization of none static methods only apply to the current instance of the class (the lock is on the class instance, e.g., this). In your example you have two different locks with no interrelation.
I don't want two threads to simultaneously call both f.get() and Foo.inc(), but these methods acquire different locks. My question is how is this preventable and is it prevented in the above code
You must share a lock to be able to arbitrate access to both f.get and Foo.inc(). You can do this either by sharing the same static lock or by the same instance lock.
These two calls do not synchronize in respect to each other.
It is as you said, a caller of f.get() acquires the lock of f object and caller of Foo.inc() acquires Foo.class object's one. So the synchronization rules are the same as if instead of static call you called an instance synchronized method with another object.

Categories