简体   繁体   中英

Synchronized code performs faster than unsynchronized one

I came out with this stunning result which i absolutely do not know the reason for: I have two methods which are shortened to:

private static final ConcurrentHashMap<Double,Boolean> mapBoolean = 
        new ConcurrentHashMap<Double, Boolean>();
private static final ConcurrentHashMap<Double,LinkedBlockingQueue<Runnable>> map
        = new ConcurrentHashMap<Double, LinkedBlockingQueue<Runnable>>();


protected static <T> Future<T> execute(final Double id, Callable<T> call){
// where id is the ID number of each thread
synchronized(id)
{
   mapBoolean.get();// then do something with the result
   map.get();//the do somethign with the result
}
}

protected static <T> Future<T> executeLoosely(final Double id, Callable<T> call){

 mapBoolean.get();// then do something with the result
 map.get();//the do somethign with the result

 }

}

On profiling with over 500 threads, and each thread calling each of the above methods 400 times each, I found out that execute(..) performs atleast 500 times better than executeLoosely(..) which is weird because executeLoosely is not synchronized and hence more threads can process the code simultaneously.

Any reasons??

The overhead of using 500 threads on a machine which I assume doesn't have 500 cores, using tasks which takes about 100-1000x as long as a lookup on a Map to execute code which the JVM could detect doesn't do anything, is likely to produce a random outcome. ;)

Another problem you could have is that a test which faster being performed with one thread can benefit from using synchronized because it biases access to one thread. ie it turns your multi-threaded test back into a single threaded one which is the fastest in the first place.

You should compare the timings you get with a single thread doing a loop. If this is faster (which I believe it would be) then its not a useful multi-threaded test.

My guess is that you are running the synchronized code after the unsynchronised code. ie after the JVM has warmed up a little. Swap the order you perform these tests and run them many times and you will get different results.

In the non synchronized scenario : 1) wait to acquire lock on a segment of the map, lock, perform operation on the map, unlock, wait to acquire lock on a segment of the other map, lock, perform operation on the other map, unlock. The segment level locking will be performed only in cases of concurrent write to the segment which doesn't look to be the case in your example.

In the synchronized scenario : 1) wait to lock, perform both the operations, unlock.

The time taken for context switching can have an impact? How many cores does the machine running the test have? How are the maps structured, same sort of keys?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM