I was reading about differences between threads and processes, and literally everywhere online, one difference is commonly written without much explanation:
If a process gets blocked, remaining processes can continue execution. If a user level thread gets blocked, all of its peer threads also get blocked.
It doesn't make any sense to me. What would be the sense of concurrency if a scheduler cannot switch between a blocked thread and a ready/runnable thread. The reason given is that since the OS doesn't differentiate between the various threads of a given parent process, it blocks all of them at once.
I find it very unconvincing, since all modern OS have thread control blocks with a thread ID, even if it is valid only within the memory space of the parent process. Like the example given in Galvin's Operating Systems book, I wouldn't want the thread which is handling my typing to be blocked if the spell checking thread cannot connect to some online dictionary, perhaps.
Either I am understanding this concept wrong, or all these websites have just copied some old thread differences over the years. Moreover, I cannot find this statement in books, like Galvin's or maybe in William Stalling's COA book where threads have been discussed.
These are resouces where I found the statements:
Many to One Model Thread management is done in user space by the thread library. When thread makes a blocking system call, the entire process will be blocked. Only one thread can access the Kernel at a time, so multiple threads are unable to run in parallel on multiprocessors.
One major problem with user-level threads is the blocking of all threads within a process when one blocks. A possible solution is known as jacketing. A blocking system call has a user-level jacket. The jacket checks to see if the resource is available, e.g., device is free.
When any user level thread makes a blocking call, the process as a whole becomes blocked. User level threads allow multiple blocking function calls to be made in parallel. In other words, while a user level thread is blocked, other user level threads can make their own blocking function calls.
Option (D): Blocking one kernel level thread blocks all related threads. false, since kernel level threads are managed by operating system, if one thread blocks, it does not cause all threads or entire process to block.
There is a difference between kernel-level and user-level threads. In simple words:
As user-level threads need to be mapped to kernel-level threads, you need to choose a suiteable mapping. You could map each user-level to a separate kernel-level thread. You could also map many user-level to one kernel-level thread. In the latter mapping, you let multiple concurrent execution paths be executed by a single thread "as we know it". If one of those paths blocks, recall that user-level threads need to yield the execution, then the executing (kernel-level) thread blocks, which causes all other assigned paths to also be effectively blocked. I think, this is what the statement refers to. FYI: In Java, user-level threads – the multithreading you do in your programs – are mapped to kernel-level threads by the JVM, i.e. the runtime system.
Related stuff:
Back in the early days of Java at least, user-level threads were called "green threads", to implement Java threading on OSes that didn't support native threading. There's still a Wiki article https://en.wikipedia.org/wiki/Green_threads which explains the origin and meaning.
(This was back when desktops/laptops were uniprocessor systems, with a single-core CPU in their 1 physical socket, and SMP machines mostly only existed as multi-socket.)
You're right, this was terrible, and once mainstream OSes grew up to support native threads, people mostly stopped ever doing this. For Java specifically at least, Green threads refers to the name of the original thread library for the programming language Java (that was released in version 1.1 and then Green threads were abandoned in version 1.3 to native threads).
So use Java version 1.3 or later if you don't want your spell-check thread to block your whole application. :P This is ancient history.
Although there is some scope for using non-blocking IO and context switching when a system call returns that it would block, but usually it's better to let the kernel handle threads blocking and unblocking, so that's what normal modern systems do.
IIRC on Solaris there was also some use of an N:M model where N user-space threads might be handled by fewer than N kernel threads. This could mean having some "peer" threads (that share the same kernel thread) like in your quote without being fully terrible purely userspace green threads.
(i.e. only some of your total threads are sharing the same kernel thread.)
pthreads on Linux uses a 1:1 model where every software thread is a separate task for the kernel to schedule.
Google found https://flylib.com/books/en/3.19.1.51/1/ which defines those thread models and talks about them some, including the N:M hybrid model, and the N:1 user-space aka green threads model that needs to use non-blocking I/O if it wants to avoid blocking other threads. (e.g. do a user-space context switch if a system call returns EAGAIN
or after queueing an async read or write.)
Okay, the other answers provide detailed information.
But to hit your main convern right in the middle:
How do Threads get blocked in Java?
sleep()
or wait()
etc, the Thread that currently executes that code (NOT the objects you call them on) will be blocked. These will get released on certain events: sleep will finish once the timer runs out or the thread gets interrupted by another, wait will release once it gets notified by another thread.synchronized(lockObj)
block or method: this will release once the other thread occupying that lockObj releases itInputStream
etc: int amountOfBytesRead = read(buffer, offset, length)
, or String line = myBufferedReader.readLine();
.parallelStream()
functions for certain long-lasting lambda functions on streams (like myList.parallelStream().forEach(myConsumerAction)
) that - if too complex or with too many elements - get handled by automated multithreading mechanisms (which you will not notice, because after the whole stuff is done, your calling thread will resume normally, just as if a normal method was called). See more here: https://www.baeldung.com/java-when-to-use-parallel-stream
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With