thread scheduling

When several processes have multiple threads, there are two levels of parallelism: processes and threads. Scheduling processing in such a system is fundamentally different, depending on whether user-level threads or kernel-level threads (or both) are supported.

Consider user-level threads first . Since the kernel does not know that there is a thread, the kernel still operates as before, selecting a process, assuming it is A, and giving A a time slice control. The thread scheduler in A decides which thread to run, let's say A1. Since there are no clock interrupts for multithreading, the thread can run for as long as it wants. If the thread uses up the entire time slice of the process, the kernel chooses another process to run.

When process A finally runs again, thread A1 will continue to run. The thread continues to consume all the time of process A until it finishes its work . However, this thread's misfit behavior does not affect other processes. The other processes will get their appropriate shares assigned by the scheduler, regardless of what happens inside process A.

Now consider the case where thread A has less work per CPU calculation, for example, 5ms of calculation work in a 50ms time slice. So, each thread runs for a while and then hands the CPU back to the thread scheduler. This way, before the kernel switches to process B, there will be a sequence of A1, A2, A3, A1, A2, A3, A1, A2, A3, A1. This situation can be represented by Figure 2-43a.

 

The scheduling algorithm used by the real-time system can be any of the algorithms described above. From a practical point of view, round-robin scheduling and priority scheduling are more commonly used. The only limitation is that the lack of a clock interrupts threads that are running too long.

Now consider the case of using kernel-level threads . The kernel chooses a specific thread to run. It doesn't care which process the thread belongs to , but it can do so if necessary. A time slice is assigned to the selected thread, and if the time slice is exceeded, the thread is forced to be suspended . A thread is blocked after 5ms in a time slice of 50ms. In a time period of 30ms, the order of threads will be A1, B1, A2, B2, A3, B3. Under this parameter and user thread state, some situations is impossible. This situation is partially depicted by Figure 2-43b.

The difference between user-level threads and kernel-level threads is performance. Thread switching for user-level threads requires a small number of machine instructions, while kernel-level threads require a full context switch, modifying the memory image, and invalidating caches, resulting in orders of magnitude latency . On the other hand, when using kernel-level threads, once the thread is blocked on I/O there is no need to suspend the entire process as in user-level threads.

Switching from a thread in process A to a thread in process B is more expensive than running a 2nd thread in process A (because the memory image must be modified, the contents of the memory cache cleared), the kernel is aware of this, and can Use this information to make decisions. For example, given two otherwise equally important threads, one of which belongs to the same process as the one that just blocked, and the other to a different process, the former should be favored.

Another important factor is that user-level threads can use thread schedulers tailored to the application. For example, consider the web server in Figure 2-8. Suppose a worker thread has just been blocked, while the dispatch thread and the other two worker threads are ready. So which one should be run? Since the runtime system understands the role of all threads, it will directly select the dispatch thread to run next, so that the dispatch thread will start another worker thread to run. In an environment where worker threads are often blocked on disk I/O, this strategy maximizes parallelism. Whereas in kernel-level threads, the kernel never understands what each thread does (although they are given different priorities). In general, however, an application-customized thread scheduler can better meet the application's needs than a kernel.


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325766807&siteId=291194637