Reputation: 375
In the book Java Concurrency in Practice by Brian Goetz et al.:
Context switches are not free; thread scheduling requires manipulating shared data structures in the OS and JVM. The OS and JVMuse the same CPUs your program does; more CPU time spent in JVM and OS code means less is available for your program. But OS and JVM activity is not the only cost of context switches. When a new thread is switched in, the data it needs is unlikely to be in the local processor cache, so a context switch causes a flurry of cache misses, and thus threads run a little more slowly when they are first scheduled. This is one of the reasons that schedulers give each runnable thread a certain minimum time quantum even when many other threads are waiting: it amortizes the cost of the context switch and its consequences over more uninterrupted execution time, improving overall throughput (at some cost to responsiveness).
Is it possible to block a thread waiting for a lock without doing a context switch (not switching in another thread)? It seems that it could be useful since context switches are expensive.
Second question: does Thread.sleep() in Java trigger a context switch?
Upvotes: 4
Views: 971
Reputation: 120858
Here is an un-popular opinion: very often you want context switching to happen. Imagine that there would be a way to prevent that, so every time a thread that needs to be taken away from the CPU
would actually just stall, it means everyone else would effectively wait, like a queue
; without given a chance to run.
Fast forward to our prod and we have pod
s that have on purpose one CPU
bound to them. If context switch would have been disabled somehow, we would not have liked that. I am OK with the context switch penalty for (almost) concurrent requests; in exchange for a single CPU
provided to a pod
(this isn't cheap in AWS/OpenShift
or the like, especially when you multiply by hundreds).
There are cases where such a scenarios might be wanted, but they don't make the rule. One exception that I am aware of (and have done it myself) is to use a spinlock based on CAS
, like AtomicInteger
and friends (that have this build in internally).
I am pretty sure that increment via CAS
will be cheaper than context switch. That being said, there is LongAdder
that says in the documentation:
But under high contention, expected throughput of this class is significantly higher, at the expense of higher space consumption.
So I guess there is simply no size fits all approach.
Thread::sleep
might issue a context switch (and most probably does), but there are no guarantees. This is not documented to do that, at least.
Upvotes: 3
Reputation: 44962
There are lock mechanism that do not require context switches e.g. Spinlock:
A spinlock is a lock which causes a thread trying to acquire it to simply wait in a loop ("spin") while repeatedly checking if the lock is available. Since the thread remains active but is not performing a useful task, the use of such a lock is a kind of busy waiting.
[...]
Because they avoid overhead from operating system process rescheduling or context switching, spinlocks are efficient if threads are likely to be blocked for only short periods. For this reason, operating-system kernels often use spinlocks. However, spinlocks become wasteful if held for longer durations, as they may prevent other threads from running and require rescheduling.
It all depends on your use case e.g. spinlocks might be useful in a real time systems while in a regular server-side application with multiple threads a regular lock will be more efficient.
Upvotes: 3