Is it always ok to use 'this' as a monitor lock?
For example, I have a class with 2 counters (in a multi-threaded environment):
public class MyClass {
private int counter1;
private int counter2;
public synchronized void increment1() {
counter1++;
}
public synchronized void increment2() {
counter2++;
}
}
Theres 2 increment operations are not related to each other . But I am using the same blocking object ( this
).
True, if clients simultaneously call methods increment1()
and increment2()
, then the call increment2
will block until the increment1()
monitor is released this
?
If this is true, does this mean that I need to provide different monitor locks for each operation (for performance reasons)?
source to share
Isn't it true that if clients call increment1 () and increment2 () at the same time, then increment2 will block until increment1 () releases this monitor?
If they are called in one instance, then yes.
If this is true, does this mean that I need to provide different monitor locks for each operation (for performance reasons)?
Only you can know this. We do not know your performance requirements. Is this actually a problem in your actual code? Are your current surgeries going to be long? Do they happen very often? Have you performed any diagnostics to assess the impact of this? Have you profiled your app to see how much time is spent looking at the monitor, let alone when you don't need it?
I would rather not sync on this
for completely different reasons. It's already hard enough to talk about streaming when you're in control, but when you don't know everything a monitor can buy, you hide out to nothing. When syncing to this
this means that any other code that has a reference to your object can also sync to the same monitor. For example, a client can use:
synchronized (myClass) {
// Do something entirely different
}
This can lead to deadlocks, performance issues, etc.
If, instead, you use a field private final
in your class, with an object created just to be a monitor, then you know that the only code acquiring that monitor will be your code.
source to share
1) yes, it is true that increment1 () blocks increment2 () and vice versa, because they both are implicitly synchronized on this
2) if you need better performance consider the java.util.concurrent.atomic.AtomicInteger class without blocking
private AtomicInteger counter1 = new AtomicInteger();
private AtomicInteger counter2 = new AtomicInteger();
public void increment1() {
counter1.getAndIncrement();
}
public void increment2() {
counter2.getAndIncrement();
}
source to share
If you synchronize a method like what you did here, you will lock the entire object, so two threads accessing another variable from the same object will block each other anyway.
If you only want to synchronize the counter at a time, so the two threads won't block each other when accessing different variables, you need to add the two counters here in the two synchronized blocks and use the different variables as a "lock" of the two blocks.
source to share
You are correct, it will be a performance bottleneck if you are using the same object. You can use different locks for a single counter or use java.util.concurrent.atomic.AtomicInteger
for a parallel counter.
how
public class Counter {
private AtomicInteger count = new AtomicInteger(0);
public void incrementCount() {
count.incrementAndGet();
}
public int getCount() {
return count.get();
}
}
source to share
Yes, this code is identical to the following:
public void increment1() {
synchronized(this) {
counter1++;
}
}
public oid increment2() {
synchronized(this) {
counter2++;
}
}
which means that only one method can be executed at a time. You must either provide different locks (and locking on this
is a bad idea to start with) or some other solution. The second is the one you really want here: AtomicInteger
source to share
If you want the performance benefits that can come from the ability to call both operations at the same time, then yes, you shouldn't provide different monitor objects for different operations.
However, there is something to be said about premature optimization that you should make sure you need it before making your program more complex to host.
source to share