Blocking Locks versus Non-Blocking Locks
Asked Answered
O

2

5

I am thinking here: If you have 2 threads executing FAST operations that need to be synchronized, isn't a nonblocking approach faster/better than a blocking/context switch approach?

By non-blocking I mean something like:

while(true) { if (checkAndGetTheLock()) break; }

The only thing I can think of is starvation (with CPU burn out) if you have too many threads looping around the lock.

How do I balance one approach versus the other?

Obryant answered 27/2, 2012 at 17:35 Comment(3)
How many lock operations will you be doing per CPU core per second?Dorset
AFAIK, the JVM does this optimization for you if there is no contention on the lock (which should be the case if the operation is fast)Whorish
@JB Nizet: I think you have to make that decision yourself by using synchronized versus ReentrantLock.Obryant
W
5

Here's what Java Concurrency in Practice says about the subject:

The JVM can implement blocking either via spin-waiting (repeatedly trying to acquire the lock until it succeeds) or bysuspending the blocked thread through the operating system. Which is more efficient depends on the relationship between context switch overhead and the time until the lock becomes available; spin-waiting is preferable for short waits and suspension is preferable for long waits. Some JVMs choose between the two adaptively based on profiling data of past wait times, but most just suspend threads waiting for a lock.

And also (which is, IMO, the most important point):

Don't worry excessively about the cost of uncontended synchronization. The basic mechanism is already quite fast, and JVMs can perform additional optimizations that further reduce or eliminate the cost. Instead, focus optimization efforts on areas where lock contention actually occurs.

Whorish answered 27/2, 2012 at 17:51 Comment(6)
I would not trust that "Some JVMs choose between the two adaptively based on profiling data of past wait times, but most just suspend threads waiting for a lock." But you can never know what those modern hotspot JVMs are capable of. I would think that synchronized is blocking and ReentrantLock is busy-waiting. But if they can change into each other at runtime I am not sure.Obryant
Where have you read that ReentrantLock is busy-waiting? If it did, it would bring the JVM to its knees for long waits. The javadoc says: A reentrant mutual exclusion Lock with the same basic behavior and semantics as the implicit monitor lock accessed using synchronized methods and statements, but with extended capabilities.Whorish
I can be wrong, but by browsing the source code i thought it was its approach: fuseyism.com/classpath/doc/java/util/concurrent/locks/… NOOOOO! The JVM does NOT use ReentrantLock for its internal things.Obryant
@Obryant The ReentrantLock is built using the AbstractQueuedSynchronizer as a synchronization mechanism. In other words the ReentrantLock uses the AbstractQueuedSynchronizer to suspend and awake threads. But as JB Nizet noted, ReentrantLock is absolutely a blocking constructDenominational
So if I want to use a busy waiting lock I have to do it myself using the atomic primitives, right?Obryant
@Obryant Yes, you can write a a simple Mutex using an AtomicBoolean. while(!flag.compareAndSet(false,true)); would be a busy-spin lock acquire.Denominational
O
2

Well the only way to be sure is test it. When it comes to multithreading and performance you simply can't assume.

Orel answered 27/2, 2012 at 17:38 Comment(2)
@Dorset well, why did you not upvote it then? I was sorely tempted to downvote it twice, but that would be unfair on M Platvoet.Tarttan
@Dorset - in that case, I'll add an upvote too, because it is the only way to be sure. Testing is important, but before a developer gets to that stage, there are some designs that will definitely result in abysmal performance, no assumptions needed. Not using them is a matter of training/experience.Tarttan

© 2022 - 2024 — McMap. All rights reserved.