Reputation: 25387
I am currently reading about Intrinsic Locks and Synchronization on oracle.com where I came to this particular example:
Synchronized statements are also useful for improving concurrency with fine-grained synchronization. Suppose, for example, class MsLunch has two instance fields,
c1
andc2
, that are never used together. All updates of these fields must be synchronized, but there's no reason to prevent an update ofc1
from being interleaved with an update ofc2
— and doing so reduces concurrency by creating unnecessary blocking. Instead of using synchronized methods or otherwise using the lock associated with this, we create two objects solely to provide locks.
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++;
}
}
}
Before this section, synchronized
methods where explained:
public synchronized void increment() {
this.c++;
}
Which should be, and please correct me if I'm wrong, the same as
public void increment() {
synchronized(this) {
c++;
}
}
if I do not add functionality to increment()
, is that correct?
My question now comes from the phrase:
but there's no reason to prevent an update of
c1
from being interleaved with an update ofc2
I am not sure if I fully understand what "interleaved" means in this context. Does it mean, that if I e.g. remove lock2
from the MsLunch
example:
public class MsLunch {
private long c1 = 0;
private long c2 = 0;
private Object lock1 = new Object();
// private Object lock2 = new Object(); // 'lock2' is no more!
public void inc1() {
synchronized(lock1) {
c1++;
}
}
public void inc2() {
synchronized(lock1) { // Using 'lock1' here too
c2++;
}
}
}
I could get in trouble with locking? Say thread-1
runs into inc1()
, gets the lock from lock1
but gets suspended before being able to increment or release the lock. Now thread-2
is entering inc2()
where another lock is created for lock1
. Is this what is being avoided by using another lock2
and is this the reason why I would not use simply this
as lock-provider? Or in other words: Can this cause a problem?
Upvotes: 1
Views: 429
Reputation: 3072
Two locks here just to have possibility to increase c1
andc2
independently and not wait when the lock is released. So if Thread-1
enters to sync block inc1
and acquires a lock1
, another Thread-2
will able increase c2
without waiting when thread-1
releases a lock.
Important to note:
Using of this
as share monitor has an own issue because a reference on the instance of MsLunch
is visible outside of MsLunch
. For example. Thread-3
able to acquire a lock for: synchronized (msLunchInstance)
outside of this class.
Upvotes: 4