speed of nested synchronized - java

Is a nested synchronized block faster to get into than a normal synchronized block? Or for example, which of the following routines is faster:
void routine1(SyncClass a) {
a.syncMethod1();
a.syncmethod2();
a.syncMethod1();
}
void routine2(SyncClass a) {
synchronized(a) {
a.syncMethod1();
a.syncmethod2();
a.syncMethod1();
}
}
The methods are synchronized. I am considering the use of a thread safe object in a situation where thread safety is not needed. So level of concurrency is not affected.
Also, is the answer platform dependant?

You're better off synchronizeding the smallest code elements you can, performance-wise, regardless of the platform.
Wrapping a number of synchronized calls in a synchronized block will reduce concurrency (and so, performance). Only do it if you need that particular sequence of calls to be synchronized.
If you're concerned about the performance impact besides that which is derived from concurrency, I don't know which is faster. However, I would expect that difference in performance in both of the methods you describe is imperceptible.

It appears that the answer is yes, as per comments left on the question. But with two caveats.
1) Due to fewer opportunities for parallel execution, threads may wait on each other more often.
2) The compiler may optimize this way automatically.

Related

Thread Safety: Maximum efficiency

Good Evening,
I am trying to understand how I am using multi-threading and how to implement thread-safety in the context.
When I want to achieve maximum speed of my threads do I use:
public void addMarketOrder(MarketOrder marketOrder) {
if (marketOrder.id != this.id) {
return;
}
synchronized (this) {
ordered += marketOrder.ordered;
}
}
or just synchronized the entire method?
public synchronized void addMarketOrder(MarketOrder marketOrder) {
if (marketOrder.id != this.id) {
return;
}
ordered += marketOrder.ordered;
}
Assuming the ids do not change, the first case is preferable to the second. The first case avoids synchronization if the ids do not match. The second case synchronizes even if there isn't any write operation.
If you want an efficient multi-threaded system, then do not let threads communicate with each other. If the threads contend for the same data, you can get significant slows downs even if you use fast alternatives like volatiles or Atomics.
I'm not sure which parts of your code need to be thread-safe. If it is only a matter of atomically increasing the counter, then making the 'ordered' field an AtomicLong and calling getAndAdd would be a reasonably fast solution that doesn't make use of any locks.
What you are hinting towards is double check locking. The correct form is:
public void addMarketOrder(MarketOrder marketOrder) {
if (marketOrder.id != this.id) {
return;
}
synchronized (this) {
if (marketOrder.id != this.id) {
ordered += marketOrder.ordered;
}
}
}
Because you shouldn't assume that because the condition became true that it will continue to be true.
Also if you read the id without synchronization it should be volatile because the compiler may optimize away memory reads under certain circumstances and the value that is being held in one thread could be different from another. Also the when not volatile the compiler can change to order of operations assuming a single thread that can make your code misbehave when running with multiple threads.
Volatility rule: any variable that is accessed outside of a synchronized block by multiple threads MUST be final or volatile. Or you will get thread visibility problems in certain circumstances.
You can also synchronize the whole method without any problem. But synchronizing the whole method will make it less efficient (which could matter if you have a lot of processors and this is a highly contested method).

Should synchronized accessed methods be synchronized?

I want to access a method from within an synchronized block. Here is an example:
public void doSomething() {
// simple stuff
// a block to reduce the synchronized code to
// what really needs to be synchronized.
synchronized(this) {
if (precondition) {
doSequentialStuff();
}
}
}
private void doSequentialStuff() {
// do stuff needs to be performed sequentially.
}
To write clean code I wondered whether it would be good to make the method doSequentialStuff explicitly synchronized. IMHO this would make no difference in semantic since the lock is in both cases this and the method is guaranteed to be accessed only from the synchronized block. I hope to increase the readability.
Any advice?
Edit:
I modified the example to incorporate the comments.
If there is no legitimate code path by which doHeavyStuff may be executed without holding the lock, then by all means make it synchronized in order to preempt any future bugs introduced by an unwary developer. The readability of code can only improve what way.
It's probably better to go with an assert to check that the lock is being held. Note, you do need assertions enabled for the check to be performed.
assert Thread.holdsLock(this);
Generally if you are using this sort of private method it tends to indicate that you should split the class into two. An outer layer does the locking and perhaps other things appropriate for the client, whereas a deeper layer is more concerned with implementation.
Use of this to lock is dubious. Generally it's better to use a private explicit lock object.
Have a look at http://weblogs.java.net/blog/mason/archive/2006/09/rechecking_doub.html, it has got similar pattern covered (uses singleton as an example, but you can easily retrofit it for your case).

Can synchronized blocks be faster than Atomics?

Suppose two following counter implementations:
class Counter {
private final AtomicInteger atomic = new AtomicInteger(0);
private int i = 0;
public void incrementAtomic() {
atomic.incrementAndGet();
}
public synchronized void increment() {
i++;
}
}
At first glance atomics should be faster and more scalable. And they are, I believe. But are they faster than synchronized blocks all the time? Or some situations exists when this rule is broken (e.g. SMP/Single CPU machine, different CPU ISA, OS'es etc.)?
incrementAndGet may well be implemented as a CAS-loop. In highly contented situations that can result in n-1 of your threads failing leading to an O(n) problem, for n threads.
( For #Geek:
Typically getAndIncrement may be implemented something like:
int old;
do {
old = value;
} while (!compareAndSet(value, old, old+1));
return old;
Imagine you have a n threads executing this code on the same atomic, and they happen to be in step with each other. The first iteration does kn work. Only one CAS will succeed. The other n-1 threads will repeat the exercise until there is only one left. So the total work is O(n^2) (worst case) instead of O(n). )
Having said that, acquiring a lock will need to do something similar at best, and locks aren't at their best when heavily contended. You're not likely to see much of an advantage for locks until you use a CAS-loop which requires significant computation before get and compareAndSwap.
Or some situations exists when this rule is broken (e.g. SMP/Single CPU machine, different CPU ISA, OS'es etc.)?
I don't know of any. (And I stand ready to be corrected ... if someone knows of a concrete counter-example.)
However (and this is my main point) there is no theoretical reason why you couldn't have a hardware architecture or a poorly implemented JVM in which synchronized is the same speed or faster than the atomic types. (The relative speed of these two forms of synchronization is an implementation issue, and as such can only be quantified for existing implementations.)
And of course, this doesn't mean you should never use synchronized. The synchronized construct has many use-cases that the atomic classes don't address.
It's implementation dependent - so ultimately you'll need to benchmark on your particualar platform / JVM / configuration.
Having said that, atomics should always be faster for the following reasons:
Atomics are designed so that the JVM can take advantage of atomic machine instructions, which are the fastest atomic operations that you can get for most platforms
synchronized makes use of relatively heavyweight locking schemes with monitor objects, which is designed to protect potentially large blocks of code. This form of locking in inherently more complicated than atomic operations so you would expect it to have higher runtime cost.
As others have said this is implementation dependent . But keep in mind that if your program invariants involve more than one variable , then you have to use synchronization to update them together . You can't do atomic operation on two related variables together just because they are of Atomic type. In that case your only friend is synchronized .
atomic variables will always be faster.
you can see that the java.util.concurrent package always utilises atomic variables rather than synchronized blocks.

What is the name of this locking technique?

I've got a gigantic Trove map and a method that I need to call very often from multiple threads. Most of the time this method shall return true. The threads are doing heavy number crunching and I noticed that there was some contention due to the following method (it's just an example, my actual code is bit different):
synchronized boolean containsSpecial() {
return troveMap.contains(key);
}
Note that it's an "append only" map: once a key is added, is stays in there forever (which is important for what comes next I think).
I noticed that by changing the above to:
boolean containsSpecial() {
if ( troveMap.contains(key) ) {
// most of the time (>90%) we shall pass here, dodging lock-acquisition
return true;
}
synchronized (this) {
return troveMap.contains(key);
}
}
I get a 20% speedup on my number crunching (verified on lots of runs, running during long times etc.).
Does this optimization look correct (knowing that once a key is there it shall stay there forever)?
What is the name for this technique?
EDIT
The code that updates the map is called way less often than the containsSpecial() method and looks like this (I've synchronized the entire method):
synchronized void addSpecialKeyValue( key, value ) {
....
}
This code is not correct.
Trove doesn't handle concurrent use itself; it's like java.util.HashMap in that regard. So, like HashMap, even seemingly innocent, read-only methods like containsKey() could throw a runtime exception or, worse, enter an infinite loop if another thread modifies the map concurrently. I don't know the internals of Trove, but with HashMap, rehashing when the load factor is exceeded, or removing entries can cause failures in other threads that are only reading.
If the operation takes a significant amount of time compared to lock management, using a read-write lock to eliminate the serialization bottleneck will improve performance greatly. In the class documentation for ReentrantReadWriteLock, there are "Sample usages"; you can use the second example, for RWDictionary, as a guide.
In this case, the map operations may be so fast that the locking overhead dominates. If that's the case, you'll need to profile on the target system to see whether a synchronized block or a read-write lock is faster.
Either way, the important point is that you can't safely remove all synchronization, or you'll have consistency and visibility problems.
It's called wrong locking ;-) Actually, it is some variant of the double-checked locking approach. And the original version of that approach is just plain wrong in Java.
Java threads are allowed to keep private copies of variables in their local memory (think: core-local cache of a multi-core machine). Any Java implementation is allowed to never write changes back into the global memory unless some synchronization happens.
So, it is very well possible that one of your threads has a local memory in which troveMap.contains(key) evaluates to true. Therefore, it never synchronizes and it never gets the updated memory.
Additionally, what happens when contains() sees a inconsistent memory of the troveMap data structure?
Lookup the Java memory model for the details. Or have a look at this book: Java Concurrency in Practice.
This looks unsafe to me. Specifically, the unsynchronized calls will be able to see partial updates, either due to memory visibility (a previous put not getting fully published, since you haven't told the JMM it needs to be) or due to a plain old race. Imagine if TroveMap.contains has some internal variable that it assumes won't change during the course of contains. This code lets that invariant break.
Regarding the memory visibility, the problem with that isn't false negatives (you use the synchronized double-check for that), but that trove's invariants may be violated. For instance, if they have a counter, and they require that counter == someInternalArray.length at all times, the lack of synchronization may be violating that.
My first thought was to make troveMap's reference volatile, and to re-write the reference every time you add to the map:
synchronized (this) {
troveMap.put(key, value);
troveMap = troveMap;
}
That way, you're setting up a memory barrier such that anyone who reads the troveMap will be guaranteed to see everything that had happened to it before its most recent assignment -- that is, its latest state. This solves the memory issues, but it doesn't solve the race conditions.
Depending on how quickly your data changes, maybe a Bloom filter could help? Or some other structure that's more optimized for certain fast paths?
Under the conditions you describe, it's easy to imagine a map implementation for which you can get false negatives by failing to synchronize. The only way I can imagine obtaining false positives is an implementation in which key insertions are non-atomic and a partial key insertion happens to look like another key you are testing for.
You don't say what kind of map you have implemented, but the stock map implementations store keys by assigning references. According to the Java Language Specification:
Writes to and reads of references are always atomic, regardless of whether they are implemented as 32 or 64 bit values.
If your map implementation uses object references as keys, then I don't see how you can get in trouble.
EDIT
The above was written in ignorance of Trove itself. After a little research, I found the following post by Rob Eden (one of the developers of Trove) on whether Trove maps are concurrent:
Trove does not modify the internal structure on retrievals. However, this is an implementation detail not a guarantee so I can't say that it won't change in future versions.
So it seems like this approach will work for now but may not be safe at all in a future version. It may be best to use one of Trove's synchronized map classes, despite the penalty.
I think you would be better off with a ConcurrentHashMap which doesn't need explicit locking and allows concurrent reads
boolean containsSpecial() {
return troveMap.contains(key);
}
void addSpecialKeyValue( key, value ) {
troveMap.putIfAbsent(key,value);
}
another option is using a ReadWriteLock which allows concurrent reads but no concurrent writes
ReadWriteLock rwlock = new ReentrantReadWriteLock();
boolean containsSpecial() {
rwlock.readLock().lock();
try{
return troveMap.contains(key);
}finally{
rwlock.readLock().release();
}
}
void addSpecialKeyValue( key, value ) {
rwlock.writeLock().lock();
try{
//...
troveMap.put(key,value);
}finally{
rwlock.writeLock().release();
}
}
Why you reinvent the wheel?
Simply use ConcurrentHashMap.putIfAbsent

Is there a way to ensure some statements are executed in atomic way

Having some line of statements, is there a simple way to assure it is executed in atomic way?
Atomic? No. Despite what people are saying here, thread-safe doesn't mean atomic:
// this is NOT atomic!
synchronized(this) {
makeChangeA();
makeChangeB();
}
if makeChangeB() throws an exception, makeChangeA() will not rollback it's change.
Definition of atomic is "executed either completely, or not at all". Synchronized block is not atomic.
If your emphasis is on "simple way", you can try out the #Synchronized annotation of Project Lombok.
synchronized (obj)
{
//any other thread synchronizing against obj waits until this block is done
}
Edit:
As road to yamburg mentioned, this is not atomicity; I had assumed you simply wanted to ensure that two blocks do not overlap in execution. If in fact you are looking for an atomic action, then you need to employ the user of transactions, which are by no means easy. See Atomicity and Transaction Processing for more info.
Furthermore, if you're guaranteeing atomicity, chances are you're also looking for consistency, isolation, and durability, collectively known as the ACID properties. These are also explained on the second page in detail.
As mentioned by others, synchronized does not provide true atomicity. However, it depends on what you want to achieve? If you’re interested in mutual exclusion only, than a synchronized block may help you very well.
Some atomic operations, however, are possible. Have a look at the package java.util.concurrent.atomic, which, for example, provides atomicIntegers which may be incremented atomically and retrieved in one step.
Otherwise you’ll need to implement your own solution, like with Semaphors which halt all other threads. But note, that even if you achieve to to block all other threads of your process their might as well other processes which interfere with what you are doing (I’m speaking of other OS processes, not only those running at the JVM).
But truly, what do you want to achieve? I’m pretty sure most daily use cases can be be tackled with synchronized blocks / methods and/or the mentioned atomic-pacakge.
put them in a synchronized block, then it is atomic for the JVM.
public class MyClass {
//the English word is synchronizer, not syncronisator
private static final Object syncronisator = new Object();
public void doSomething() {
doSomethingNotSyncronized();
synchronized(syncronisator) {
doItAtomic1():
doItAtomic2():
}
doSomethingNotSyncronized2();
}
}
BTW: if you want to synchronize the complete method with the instance of MyClass, then you could use:
public class MyClass {
public void synchronized doSomething() {
doItAtomic1():
doItAtomic2():
}
}
Edit:
Road to yamburg is right, atomic is not only synchronization, but mean also everything or none.

Categories

Resources