5. Chapter 5: Distributed Operating System
5.5. Threads
- Architectures for multi-threaded servers
- The worker pool architecture
- The server creates a fixed pool of ‘worker’ threads to process the requests when it starts up.
- The module marked ‘receipt and queuing’ is typically implemented by an ‘I/O’ thread, which receives requests from a collection of sockets or ports and places them on a shared request queue for retrieval by the workers.
- There is sometimes a requirement to treat the requests with varying priorities.
- Thread-per-request architecture
- I/O thread spawns a new worker thread for each request
- Worker destroys itself when it has processed the request against its designated remote object.
- The threads do not contend for a shared queue.
- Throughput can be maximized because the I/O thread can creates as many workers as there are outstanding requests.
- But, overhead of the thread creation and destruction operations.
- Thread-per-connection architecture
- Associates a thread with each connection
- The server creates a new worker thread when a client makes a connection and destroys the thread when the client closes the connection.
- Client may make many requests over the connection, targeted at one or more remote objects.
Figure : Alternative server threading architectures

- Thread-per-object architecture
- Associates a thread with each remote object.
- An I/O thread receive requests and queues them for the workers, but this time there is a per-object queue.
- For the last two architectures, the server benefits from lower thread-management overhead compared with the thread-per-request architecture.
- But, client maybe delayed while a worker thread has several outstanding requests but another thread has no work to perform.
- Threads within clients
- Can be useful for clients as well as servers.
- Client process with two threads.
- First thread: generates results to be passed to a server by remote method invocation, but does not require a reply. (Remote method invocation blocks the caller.)
- Second thread: performs the remote method invocations and blocks while the first thread is able to continue computing further results.
- First thread places its results in buffers, which are emptied by the second thread.
- First thread is only blocked when all the buffers are full.
- Thread versus multiple processes
- Threads are cheaper to create and manage than processes
- Resource sharing can be achieved more efficiently between threads than between processes because threads share an execution environment.
- Switching to a different thread within the same process is cheaper than switching between threads belonging to different processes.
- Threads within a process may share data and other resources conveniently and efficiently compared to separate processes.
- But, threads within a process are not protected from one another.
Figure : State associated with execution environments and threads

- Thread programming
- Concurrent programming
- Much threads programming is done in a conventional language, such as C with threads library.
- POSIX Threads standard IEEE 1003.1c-1995, known as pthreads, has been adopted recently.
- Some languages provide direct support for threads, including Ada95 [Burns and Wellings 1998], Modula-3 [Harbison 1992] and Java [Oaks and Wong 1999].
- Java provides method for creating threads, destroying them and synchronizing them.
Figure : Java thread constructor and management methods

- Thread synchronization
- Thread scheduling
- Preemptive scheduling
- A thread maybe suspended at any point to make way for another thread, even when the preempted thread would otherwise continue running.
- Non-preemptive scheduling
- A thread runs until it makes a call to the threading system, then the system may deschedule it and schedule another thread to run.
- Race condition can be avoided.
- But, cannot take the advantage of multiprocessor, since they run exclusively.
- Care must be taken over long-running sections of code that do not contain calls to the threading system.
- Unsuited to real-time applications.
- Thread implementation
- Many kernels provide native support for multi-threaded processes, including Windows, Linux, Solaris, Mach and Mac OS X.
- When no kernel support for multi-threaded processes is provided, a user-level thread implementation suffers from the following problems:
- The threads within a process cannot take advantage of a multiprocessor.
- A thread that takes a page fault blocks the entire process and all threads within it.
- Threads within different processes cannot be scheduled according to a single scheme of relative prioritization.
- Thread implementation
- User-level threads implementations, have significant advantages over kernel-level implementations:
- Certain thread operations are significantly less costly.
- Given that the thread-scheduling module is implemented outside the kernel, it can be customized or changed to suit particular application requirements.
- Many more user-level threads can be supported than could reasonably be provided by default by a kernel.