Final Flashcards
What is a thread?
In computer science, a thread of execution is the smallest sequence of programmed instructions that can be managed independently by a scheduler, which is typically a part of the operating system.
What is a heavyweight process?
A normal process under an OS is a “heavyweight process.” For each such process, the OS provides an independent address space to keep different users and services separated. Switching from one such process to another is time-consuming, and this task is performed by the Memory Management Unit (MMU).
Why do we call a thread a lightweight process (LWP)?
A thread is called a lightweight process (LWP) because it runs under the address space of a regular (heavy-weight) process, and LWPs under the same process may share, e.g., variables. Switching from one LWP to another is much faster than switching from one heavyweight process to another, because there is less to manage, and the MMU is not involved.
What is the difference between a thread and a process?
Threads within the same process run in shared memory space, while processes run in separate memory spaces. Processes are independent of one another, and they don’t share their code, data and OS resources. Threads share their code section, data section and OS resources (like files and signals) with other threads. But, like a process, a thread has its own program counter (PC), register set and stack space.
Are there situations that we use multithreading?
Multithreading has many advantages, but in the following two cases, multithreading is preferable over a single thread process:
A) Processing power: if you have a multi-core computer system, multithreading is preferable.
B) Multithreading avoids priority inversion where a low priority activity such as accessing the disk, blocks a high priority activity, such as user interface responding to a request.
What is an example of a situation where having a single thread is preferred over multithreading?
If we are waiting for a user response or we are waiting for data to arrive over the network, it is useless to assign several threads to wait for the same thing.
How would a web-server act under a multithreading system?
The server listens for a new client to ask for a transaction. Then the server would assign a thread to the requesting client and start listening for the next client.
What is the difference between running four threads on a single core processor and running the same number of threads on a double core processor. Explain concurrency and parallelism using single core and double core processors.
On a single core processor, all of the threads take turns in a round robin fashion. This is known as “concurrency.” On a double core processor, two threads run (concurrently) on one processor and the other two would run on the second one. This parallel running of threads on multiple cores is known as “parallelism”.
What are the four benefits of multithreading?
- Responsiveness: If a process is divided among multiple threads, then if one part of the process is blocked, the other parts could go on.
- Resource sharing: Different threads of a process can share code and memory of that process.
- Economy: Starting a new thread is much easier and faster than starting a new process.
- Scalability: A multithreaded process runs faster if we transfer it to a hardware platform with more processors.
What are the challenges programmers face when they design the code for multiprocessors?
In general, five areas present challenges in programming for multicore systems.
- Identifying tasks (dividing activities): Involves examining applications to find areas that can be divided into separate, concurrent tasks.
- Balance. Programmers must ensure that tasks are of the same value in terms of complexity and execution time.
- Data splitting. Data must be split, in a balanced manner, among already split concurrent tasks.
- Data dependency. Programmers must ensure that different tasks that are running concurrently do not have data dependence.
- Testing and debugging. Many different execution paths are possible, which is more complicated to test and debug than single-threaded applications.
What are the two types of parallelism?
Data parallelism and task parallelism.
Data parallelism: Data is divided into subsets and each subset is sent to different threads. Each thread performs the same operation.
Task parallelism: The whole data is sent to different threads, and each thread does a separate operation.
How do we compute speedup using Amdahl’s law?
speedup <= 1 / (S + ((1 - S) / N)
(S is serial portion, N is number of processing cores.) Speedup indicates how much faster the task is running on these N processors as compared to when it was running serially.
Suppose that 50% of a task can be divided equally among ten threads and each thread will run on a different core.
a) What is the speedup of this multithreading system as compared to running the whole task as a single thread?
b) What is the speedup of part A if we could send 90% of the job to ten threads?
a) speedup <= 1 / ((0.5 + (0.5 / 10))) <= 1.8
b) speedup <= 1 / ((0.1 + (0.9 / 10))) <= 5.3
What is the upper bound in Amdahl’s law?
The upper bound in Amdahl’s law is that as N approaches infinity, the speedup converges to 1 / S. E.g., if 40% of an application is performed serially, the maximum speedup is 2.5 times, regardless of the number of processing cores we add.
In the context of Amdahl’s law, what is the meaning of “diminishing returns?”
The upper bound of speedup = 1/S is still an optimistic estimation. When the number of processors and threads increase, the overhead of handling them increases too. Too much increase in the number of threads could cause a loss, and the speedup may fall below 1/S. This is known as a diminishing return, which says that sometimes a smaller number of threads could result in higher performance.
What are the three most popular user-level thread libraries?
POSIX Phtreads, Windows and Java.
What is the relationship between user threads and kernel threads?
User threads run within a user process. Kernel threads are used to provide privileged services to processes (such as system calls). They are also used by the kernel to keep track of what is running on the system, how much of which resources are allocated to what process, and to schedule them. Hence, we do not need to have a one-to-one relationship between user threads and kernel threads.
a) In the relationship between the user and kernel threads, what is the many-to-one model?
b) What is the shortcoming of this model?
a) Before the idea of threads became popular, OS kernels only knew processes. An OS would consider different processes as separate entities. Each process was assigned a working space and could produce system calls and ask for services. Threading in the user space was not dealt with by the OS. With user mode threading, support for threads was provided by a programming library, and the thread scheduler was a subroutine in the user program itself. The OS would see the process, and the process would schedule its threads by itself.
b) The shortcoming of this model is if one of the user threads needed a system call, such as a page fault, then the other threads were blocked.
a) What is the one-to-one threading model?
b) What are its advantages and shortcomings?
a) The one-to-one model maps each user thread to a kernel thread.
b) An advantage of the one-to-one threading model is that it provides more concurrency than the many-to-one model by allowing another thread to run when a thread makes a blocking system call. It also allows multiple threads to run in parallel on multiprocessors.
The shortcoming occurs when there are too many user threads, which may burden the performance of the operating system.
What is a many-to-many multithreading model?
The OS decides the number of kernel threads, and the user process determines the number of user threads. A process that runs on an eight-core processor would have more kernel threads than the one which runs on a quad-core processor. This model does not suffer from either of the shortcomings of the other two models.
What is pthread?
It is POSIX (portable OS interface) thread library providing programmers with application program interface (API) for creating and managing threads.
What is synchronous threading?
The parent, after creating the threads, has to wait for the children to terminate before it can resume operation.
For thread programming in C or C++ using pthread, what header file should be included?
include (less than sign)pthread.h(greater than sign)
- What does the following piece of code do?
It uses a function to perform summation. The main program sequentially calls the function. It takes in an array, then calculates the sum from i to n for each number in the array.
- What does the following piece of code do?
His answer: It creates several threads. The number of threads is equal to the number of arguments that are sent to the main process. All threads are the same and perform a summation. When all threads are finished, they are joined with the main process.
What is the difference in the behavior in the code in question 27 and 28?
27 uses a function for summation. It is called, and the main program has to wait for it to finish. Then the program can call it again. 28 uses threads. The main program creates all threads, and they run concurrently. The order that the threads finish their work in depends on the complexity of their job.
What does the following instruction do? pthread_create(id, attributes, function, argument)
It creates a thread with a given id and a set of attributes. The thread will run a function and can carry an argument into that function.
What does the following instruction do? pthread_join(id, ReturnedValue)
The main process waits for the thread with the given ID to finish and returns a variable. If no variable is to be brought back, NULL is used.
Does Windows support multithreading? Explain.
Windows supports multithreading. It supports single or multiple thread creation and single or multiple thread joining.
What does detaching of thread mean?
If pthread_detach() is used inside a thread, it means that as soon as the thread is exited, its resources are released, and the system should not wait for this thread to join with its parent.
What is meant by implicit threading?
It is difficult to create hundreds and thousands of threads by programming. The solution is implicit threading, which transfers the creation and management of threading from application developers to compilers and run-time libraries.
What are some popular implicit threading examples?
- Thread pools
- Fork-join
- OpenMP
- Grand Central Dispatch
- Intel Threading Building Blocks
How is OpenMP application programming interface used?
The programmer determines which parts of the program could be implemented in a parallel manner. Then the OpenMP API is used, which has compiler directives and library routines. The compiled version of the program would have multiple threads to perform the code in a parallel manner.
What happens when fork() is used in a program?
fork() is the UNIX way of creating a new separate duplicate process. The new process consists of a copy of the address space of the original process. Both processes (the parent and the child) continue execution at the instruction after the fork(). fork() returns a code. The child process receives a zero from the fork(). The parent process receives a nonzero ID of the child.
When a fork() is executed, do the threads running under the parent process get duplicated?
The threads are not duplicated unless the exec() instruction is executed after fork().
What is a signal in the context of threading?
Signals notify a process of occurrence of an event. A signal can be synchronous or asynchronous. A signal is generated, delivered and then handled.
What are two examples of synchronous and asynchronous signals?
Examples of synchronous signals include illegal memory access and division by 0. Synchronous signals are delivered to the same process that performed the operation that caused the signal (that is the reason they are considered synchronous).
When a signal is generated by an event external to a running process, that process receives the signal asynchronously. Examples of such signals include terminating a process with specific keystrokes (such as controlC and having a timer expire.
Is it possible to create a thread and then cancel it?
Yes. The main thread could cancel the child thread unless the thread has disabled its cancellation. The thread can disable its cancellation, but it is better to enable it again.
In the context of scheduling user threads and assigning it to a kernel thread, what is a lightweight process?
To the user-thread library, the LWP appears to be a virtual processor on which the application can schedule a user thread to run.
What is a cooperating process, and why is there a potential of data inconsistency?
A cooperating process can affect or be affected by other processes. They use shared memory to share data or to pass messages. The sequence of actions of cooperating processes could result in the wrong content of the shared memory. Wrong content of shared memory is referred to as data inconsistency.
Why is there a need for synchronization?
Data inconsistency requires that the cooperating processes or threads access shared variables in an orderly manner, which is called synchronization.
What is the “consumer-producer” problem in the context of synchronization? Explain the simple solution of using a “counter.”
Two processes are there. One process produces data, and the other process reads it (consumes it). There could be data inconsistency if the two participants don’t follow a rhythm. The producer should first write into a buffer and increase the counter; then the consumer should read the data and decrease the counter.
In the “producer-consumer” problem, for synchronous passing of data, what are the “blocking send” and “blocking receive” strategies?
If these two strategies are applied, then the sender is blocked until the receiver verifies the reception of the data. Also, the receiver is blocked from reading a data until the sender verifies that a new data is placed into the buffer.
What is a “race condition” in the producer-consumer problem?
Both the producer and the consumer can access the shared variable “counter.” The producer will increment, and the consumer will decrement the variable, independent of each other. The final value of the counter depends on the order that these processes update the variable. The solution is to not allow both processes to access the shared variable concurrently.
The “critical section” problem is a synchronization protocol. Explain its four steps.
- Entry section: A process requests to enter its critical section.
- Critical section: Only one process can enter its critical section. A critical section is where the process shares or changes shared variables.
- Exit section: After finishing its critical section, the process exits, and one of the other processes could enter its critical section.
- Remainder section: A process could continue with other jobs following exiting the critical section. The remainder section of processes could be done concurrently.
What are the three conditions of the critical section protocol?
1) Mutual exclusion: Only one process could be in its critical section.
2) Progress: If no process is executing in its critical section and some processes wish to enter their critical sections, then only those processes that are not executing in their remainder sections can participate in deciding which will enter its critical section next, and this selection cannot be postponed indefinitely.
3) Bounded waiting: There should be a bound on the number of times that other processes could enter their critical section before a process which has requested should wait.
What is Peterson’s solution for synchronization?
Peterson’s solution is for two processes. It assumes an atomic “load” and “store”. It requires two shared variables of int turn and boolean flag[2]. Each process can turn its flag bit to 1 to declare its intention of entering the critical section. Turn variable shows the process number that is allowed to enter its critical section. Each process i sets its flag to 1 and sets the turn variable to j (offer the other process to run). Then process i arrives at its critical section and keeps waiting there by testing the turn variable to see if it is its turn.
What is mutex and how does it help synchronization?
Complicated implementations have made synchronizing threads by OS and hardware. Mutex is a synchronization primitive available to programmers. A mutex has a binary “lock”, which is accessed by acquire() and then is release by release().
52.One thread is supposed to perform the following function:
A) tid[2] is a global variable. What is the purpose of this line?
B) What is the purpose of this line of code? pthread_mutex_t_ lock;
C) What happens to the thread when it reaches this line and its mutex lock is not open? pthread_mutex_lock(&lock);
D) In general, what do we call this portion of the thread?
E) What is the result of the execution of this line of code? pthread_mutex_unlock(&lock)
A) This is thread ID. In this example, there are two threads.
B) A global variable called “lock” is generated of the type mutex. This variable is either 0 or 1.
C) This instruction reads the mutex lock and if it is free, it will make it busy and start its critical section.
D) This is the critical section of the thread. While this thread is busy doing its critical section, other threads cannot intervene because only this thread has the mutex lock.
E) When the thread finishes its critical section, it will release the lock, and other threads that are waiting for the lock can acquire it.
What is a semaphore?
A semaphore is a signaling mechanism. A thread that is waiting on a semaphore can by signaled by another thread. Mutex allows a thread to hold the lock and then release the lock. Using mutex, when the lock is released, any thread that is waiting could acquire the lock, but using semaphore, a thread could pass the lock to a specific thread.
What is an “atomic” operation, and why is it important to have atomic operations for synchronization?
Operations that are used for synchronization are more complex than usual operations. E.g, wait() operation in mutex lock handling should read the mutex lock and if it is “free”, then it should change the mutex lock to “unavailable.” A non-atomic operation may read the variable and before it changes the value of the variable, another thread may have done the same thing. Then each thread thinks it has changed the lock value and it owns the lock. An atomic operation allows only one thread to first read and then change the variable without any interference from other threads.
What are the purposes of wait() and signal() operations in the context of semaphores?
The wait() operation lets the thread keep checking the semaphore lock until the lock is released by the holder. The operation is atomic. If the lock that is read is free then the lock is changed to "unavailable" for the rest of the thread. The signal() operation releases the semaphore lock to a designated semaphore holder.
56. Explain the purpose of parts A-E. A) sem_t sem_example; B) if (passed_in_value == 1) for (i = 0; i < 0xFFFF' ++i); C) sem_wait(&sem_example); D) See code E) sem_post(&sem_example)
A) Defines the variable sem_example as a binary semaphore.
B) Delays thread1 to show that the order of generation of threads is not essential and when one thread is finished, the other thread receives the semaphore.
C) A thread waits here till the semaphore is released.
D) This is the critical section of the code.
E) This thread signals the release of the semaphore to the other holder of the semaphore.