📝 Synchronization hardware in operating system (54 MCQs)
📖 From Operating System • 5. Process Synchronization • 54 questions available
What is Synchronization hardware in operating system?
Definition:
Synchronization hardware refers to special atomic machine instructions like Test-and-Set or Compare-and-Swap that execute indivisibly to implement locking primitives efficiently.
Example:
The instruction atomically reads memory location and sets it to 1, returning the old value in a single cycle .
Reason:
Hardware support eliminates the race condition inherent in software-only lock implementations by guaranteeing that read-modify-write operations cannot be interrupted by context switches.
📝 All Synchronization hardware in operating system MCQs
Q1. What is the fundamental premise behind hardware-based solutions for the critical-section problem?
📖 Explanation: Hardware solutions to the critical-section problem are based on the concept of locking. They use special instructions to create locks that protect critical regions, ensuring that only one process can access shared data at a time. This is a more fundamental approach than software-only solutions.
Q2. In a single-processor environment, how can the critical-section problem be solved simply?
📖 Explanation: In a single-processor system, disabling interrupts prevents context switching. This ensures that the current sequence of instructions executes without preemption, guaranteeing that no other process can modify the shared variable. This is a straightforward approach used by nonpreemptive kernels.
Q3. Why is disabling interrupts not a feasible solution for critical-section protection in a multiprocessor environment?
📖 Explanation: Disabling interrupts on a multiprocessor is inefficient because it requires broadcasting a message to all processors. This message passing delays entry into each critical section and decreases system efficiency. This makes it an impractical approach for large-scale multiprocessor systems.
Q4. Which characteristic of the `test and set()` instruction makes it useful for solving the critical-section problem?
📖 Explanation: The key characteristic of the `test and set()` instruction is its atomic execution. It reads and modifies a memory location as a single, uninterruptible operation. This atomicity is crucial for implementing mutual exclusion without the risk of race conditions.
Q5. What does the `test and set()` instruction return?
📖 Explanation: The `test and set()` instruction returns the original value of the target variable. This allows a process to test if the lock was free before setting it. If the original value was false (0), the lock is acquired; if true (1), the lock was already held.
Q6. How does the `test and set()` instruction implement mutual exclusion?
📖 Explanation: Mutual exclusion with `test and set()` uses a shared boolean lock variable initialized to false. A process repeatedly calls `test and set(&lock)` in a while loop until it returns false, indicating the lock was free and the process has acquired it. The lock is released by setting it to false.
Q7. What is the purpose of the `compare and swap()` instruction?
📖 Explanation: The `compare and swap()` instruction is an atomic operation that compares the current value of a variable with an expected value. If they match, it sets the variable to a new value. It always returns the original value, providing a powerful tool for lock acquisition.
Q8. How many operands does the `compare and swap()` instruction operate on?
📖 Explanation: The `compare and swap()` instruction operates on three operands: the memory location (`value`), the expected value, and the new value. This makes it more flexible than `test and set()` for implementing various synchronization primitives.
Q9. In the mutual-exclusion implementation using `compare and swap()`, what value must the global lock variable be initialized to?
📖 Explanation: The global lock variable is initialized to 0. This value represents the unlocked state. The first process that calls `compare and swap(&lock, 0, 1)` will find that `lock == expected (0)` and will set it to 1, acquiring the lock and returning 0.
Q10. What does the while loop condition `while (compare and swap(&lock, 0, 1) != 0)` check in the mutual-exclusion implementation?
📖 Explanation: The while loop condition is a busy-waiting mechanism. It repeatedly calls `compare and swap(&lock, 0, 1)` which returns the original value of lock. The loop continues as long as the return value is not 0, meaning the lock was not free. When it returns 0, the lock was acquired and the process enters the critical section.
Q11. What is the primary limitation of the basic `test and set()` and `compare and swap()` mutual-exclusion algorithms?
📖 Explanation: The basic algorithms using `test and set()` and `compare and swap()` successfully enforce mutual exclusion but fail to guarantee bounded waiting. A process could be indefinitely bypassed by others, leading to starvation. This is a significant limitation that requires additional logic to address.
Q12. In the bounded-waiting mutual exclusion algorithm using `test and set()`, what is the purpose of the `waiting` array?
📖 Explanation: The `waiting` array is a boolean array where `waiting[i]` is `true` if process Pi is waiting to enter its critical section. This array, along with the `lock` variable, is used to implement a fair mechanism that ensures bounded waiting.
Q13. What is the role of the `lock` variable in the bounded-waiting `test and set()` algorithm?
📖 Explanation: The `lock` variable acts as a global lock for the critical section. It is used in conjunction with the `waiting` array to control access. The `test and set()` instruction is used to atomically test and set this lock, ensuring only one process can acquire it at a time.
Q14. In the bounded-waiting `test and set()` algorithm, after a process exits its critical section, what action does it take?
📖 Explanation: Upon exiting, a process scans the `waiting` array in a cyclic order starting from `(i+1) % n`. It designates the first process with `waiting[j] == true` as the next to enter. If no process is waiting, it releases the lock by setting `lock = false`. This ensures fairness.
Q15. What proof is provided to show that the bounded-waiting algorithm maintains mutual exclusion?
📖 Explanation: Mutual exclusion is proven by noting that a process can enter its critical section only if `waiting[i] == false` or `key == false`. The value of `key` becomes false only when a process successfully executes `test and set()`. The first process to do so enters; others must wait, ensuring only one process is in the critical section.
Q16. How is the bounded-waiting requirement satisfied in the advanced `test and set()` algorithm?
📖 Explanation: Bounded waiting is satisfied because when a process exits its critical section, it scans the `waiting` array in cyclic order and chooses the first waiting process. This guarantees that any process waiting to enter will be selected within at most `n-1` turns of the scanner, limiting the number of times it can be bypassed.
Q17. What happens in the bounded-waiting algorithm if no other process is waiting when a process exits its critical section?
📖 Explanation: If no process is waiting (`waiting[j]` is false for all j), the exiting process sets `lock = false`. This releases the lock, allowing any future process to compete for it using the `test and set()` instruction. This ensures the system remains responsive and can handle new requests.
Q18. What is the significance of the `key` variable in the bounded-waiting algorithm?
📖 Explanation: The `key` variable is used to store the result of the `test and set(&lock)` operation. If `test and set()` returns `false`, `key` becomes `false`, allowing the process to enter the critical section. If it returns `true`, `key` remains `true`, and the process continues to wait.
Q19. Which of the following is a true statement about hardware synchronization instructions?
📖 Explanation: Hardware synchronization instructions like `test and set()` and `compare and swap()` simplify the implementation of mutual exclusion by providing atomic operations. They are widely supported on modern processors and form the foundation for higher-level synchronization primitives.
Q20. What problem does the bounded-waiting `test and set()` algorithm address that the basic `test and set()` algorithm does not?
📖 Explanation: The basic `test and set()` algorithm ensures mutual exclusion and progress but does not guarantee bounded waiting. The advanced algorithm explicitly adds logic to ensure bounded waiting, preventing starvation by selecting waiting processes in a fair, cyclic order.
Q21. What does the `test and set()` instruction do when it executes atomically?
📖 Explanation: The `test and set()` instruction atomically tests a boolean variable and sets it to `true`. The original value of the variable is returned. This atomicity ensures that two concurrent calls cannot interfere, preventing race conditions.
Q22. In the `compare and swap()` definition, what is returned when the comparison fails (the expected value does not match the current value)?
📖 Explanation: The `compare and swap()` instruction always returns the original value of the variable, regardless of whether the comparison succeeds or fails. This allows the caller to know the state of the variable and act accordingly, which is essential for implementing various synchronization patterns.
Q23. How does a process release the lock in the basic mutual-exclusion implementation using `test and set()`?
📖 Explanation: After executing its critical section, a process releases the lock by setting the shared `lock` variable to `false`. This allows other processes to acquire the lock and enter their critical sections. This is the standard unlock pattern for a boolean lock.
Q24. What is the order of the cyclic scan in the bounded-waiting algorithm when process Pi exits its critical section?
📖 Explanation: The algorithm specifies that the scan starts at `j = (i + 1) % n`, the process immediately after the one that just exited. It then iterates through the array in a cyclic fashion until it finds a waiting process or returns to i, ensuring a fair and systematic search.
Q25. What will a process do in the bounded-waiting algorithm if it finds a waiting process during the exit scan?
📖 Explanation: When the exiting process finds a waiting process `Pj` (with `waiting[j] == true`), it sets `waiting[j] = false`. This signals to Pj that it can enter its critical section. This is the mechanism by which the lock is transferred to the next waiting process in a fair manner.
Q26. In the basic mutual-exclusion algorithm with `compare and swap()`, what happens when a process attempts to acquire the lock while it is already held?
📖 Explanation: If the lock is already held (`lock == 1`), the `compare and swap()` will return 1 (the original value). Since the while loop condition checks for a return value not equal to 0, the process will continue to loop, busy-waiting until the lock is released by the holding process and set back to 0.
Q27. Why is disabling interrupts in a multiprocessor system considered time-consuming?
📖 Explanation: Disabling interrupts on a multiprocessor requires sending a message to every processor in the system. The time to deliver and process these messages, along with the synchronization overhead, makes this operation costly and inefficient, especially for frequently executed critical sections.
Q28. What is the primary advantage of using hardware instructions like `test and set()` for synchronization?
📖 Explanation: The primary advantage is atomicity. Hardware instructions are executed as a single, uninterruptible unit by the CPU. This atomicity guarantees that the operation completes without interference, making it a reliable and efficient foundation for implementing mutual exclusion, regardless of the system's scheduling policy.
Q29. What is the main drawback of busy-waiting solutions like the ones using `test and set()`?
📖 Explanation: Busy-waiting solutions cause a process to repeatedly execute a loop checking the lock. This consumes CPU cycles that could be used by other processes. While acceptable for short waits or when few processes are involved, it is generally considered inefficient for long waits or high-contention scenarios.
Q30. What is the role of `waiting[i]` in the entry section of the bounded-waiting algorithm?
📖 Explanation: In the entry section, a process sets `waiting[i] = true`. This signals its intention to enter the critical section. This flag is then used by the scanning process during the exit section to identify which process should be granted access next, implementing the bounded waiting property.
Q31. In the `compare and swap()` instruction, if the current value of the variable is not equal to the expected value, what happens to the variable?
📖 Explanation: The `compare and swap()` instruction is conditional. It only changes the variable to the new value if the current value matches the expected value. If they do not match, the variable remains unchanged, and the instruction simply returns the current value. This conditional behavior is central to its use in lock implementations.
Q32. Why is `compare and swap()` considered more powerful than `test and set()`?
📖 Explanation: `compare and swap()` is more powerful because it can test for a specific expected value and only perform the swap if that condition is met. This allows for more complex synchronization patterns, such as implementing counting semaphores or handling multiple states, beyond a simple boolean lock.
Q33. What is the structure of a process using the basic `test and set()` instruction for mutual exclusion?
📖 Explanation: The correct structure is: 1) A while loop that busy-waits using `test and set(&lock)` until it returns false (acquiring the lock). 2) The critical section. 3) Releasing the lock by setting `lock = false`. 4) The remainder section. The other options have incorrect logic or use the wrong instruction.
Q34. In the bounded-waiting `test and set()` algorithm, what is the initial state of the `waiting` array and the `lock` variable?
📖 Explanation: The data structures are initialized to false. This means no process is initially waiting (`waiting[i] == false` for all i), and the lock is free (`lock == false`). This provides a clean starting state for the mutual-exclusion algorithm.
Q35. What is the main reason software-based solutions like Peterson's are not guaranteed to work on modern architectures?
📖 Explanation: Modern CPUs and compilers often reorder memory operations for performance optimization. Peterson's solution relies on the order of operations being exactly as written in the code. This reordering can lead to the algorithm's proof of correctness being invalid, allowing race conditions to occur.
Q36. What does the `test and set()` instruction do to the target variable?
📖 Explanation: The `test and set()` instruction unconditionally sets the target variable to true. This is a fundamental part of its operation. The test part is returning the original value, while the set part always sets it to true. This ensures that a lock, once acquired, is held.
Q37. How does the bounded-waiting algorithm ensure that a process cannot enter the critical section unless it is its turn?
📖 Explanation: The combination of the `waiting` flag and the `test and set()` operation achieves this. In the entry section, a process first sets `waiting[i] = true` and then attempts to acquire the lock using `test and set(&lock)`. It will only enter the critical section if its `waiting[i]` flag is set to false by another process or if `key` (the result of `test and set()`) is false.
Q38. What is the purpose of the `while ((j != i) && !waiting[j])` loop in the bounded-waiting algorithm's exit section?
📖 Explanation: This loop iterates through the `waiting` array starting from `(i+1) % n`. It continues as long as `j != i` (it hasn't gone through the entire array) and the current process `Pj` is not waiting (`!waiting[j]`). Its goal is to find the first process in the cyclic order that is waiting to enter.
Q39. What happens to the `waiting` flag of a process selected to enter the critical section by the scanner?
📖 Explanation: When the scanner finds a waiting process `Pj`, it sets `waiting[j] = false`. This effectively grants Pj permission to enter its critical section, as the entry condition for Pj (in its while loop) is `waiting[j] && key`. Setting `waiting[j]` to false breaks the loop, allowing Pj to proceed.
Q40. What is the main advantage of hardware synchronization over disabling interrupts?
📖 Explanation: While disabling interrupts works in single-processor systems, it is inefficient in multiprocessor systems. Hardware synchronization instructions, being local to each processor and atomic, provide an efficient and scalable way to implement mutual exclusion in multiprocessor environments without the overhead of broadcasting messages.
Q41. What is the effect of a process executing `key = test and set(&lock)` in the bounded-waiting algorithm?
📖 Explanation: The `test and set(&lock)` instruction returns the original value of `lock` into `key` and atomically sets `lock` to true. This allows the process to see if the lock was free (`key == false`) or held (`key == true`), and if free, it atomically acquires it by setting it to true.
Q42. Which of the following is NOT a characteristic of the advanced `test and set()` algorithm for bounded waiting?
📖 Explanation: The advanced bounded-waiting algorithm uses a `waiting` array and a `lock` variable, and scans the `waiting` array cyclically. It does not use a `turn` variable, which is a characteristic of Peterson's solution. This algorithm uses the `waiting` flags and the lock to achieve its goals.
Q43. What is the maximum number of turns a process can wait in the bounded-waiting algorithm before entering its critical section?
📖 Explanation: The algorithm guarantees bounded waiting with a bound of `n-1` turns. When a process exits, it scans from `(i+1) % n` to `(i-1) % n`. A waiting process will be found and selected within at most `n-1` steps of this cyclic scan. This ensures a process cannot be bypassed indefinitely.
Q44. How does the `compare and swap()` instruction help in implementing a spinlock?
📖 Explanation: `compare and swap()` is ideal for spinlocks. A spinlock uses a variable (e.g., `lock`). A process repeatedly calls `compare and swap(&lock, 0, 1)` to acquire it. The atomicity of the instruction ensures that only one process can successfully change the variable from 0 to 1, making it a simple and effective lock primitive.
Q45. What is the primary drawback of using busy-waiting in a system with a single CPU?
📖 Explanation: On a single CPU, a process that is busy-waiting is consuming CPU cycles while doing no useful work. This prevents other, potentially ready, processes from running, leading to inefficient CPU utilization. This is a major reason why busy-waiting is often avoided in favor of blocking mechanisms.
Q46. What condition must be true for process Pi to enter its critical section in the bounded-waiting algorithm?
📖 Explanation: Process Pi can enter its critical section only if its `waiting[i]` flag is set to false by the exiting process, or if it successfully acquires the lock via `test and set()`, resulting in `key == false`. This dual condition is what allows the algorithm to implement fair access.
Q47. Which of the following is an example of a special hardware instruction used for synchronization?
📖 Explanation: `test and set()` is a classic example of a special hardware instruction designed for synchronization. It atomically tests the value of a memory location and sets it to a specific value, making it a fundamental building block for implementing mutual exclusion.
Q48. What is the relationship between the `lock` variable and the `waiting` array in the bounded-waiting algorithm?
📖 Explanation: The `lock` variable is used to enforce mutual exclusion on the critical section itself. The `waiting` array is a separate mechanism used to track which processes are waiting and to ensure that the selection of the next process is fair, thus satisfying the bounded-waiting requirement.
Q49. What would happen if the `while (compare and swap(&lock, 0, 1) != 0)` loop in the basic algorithm were removed?
📖 Explanation: The while loop is essential for mutual exclusion. Without it, a process would simply call `compare and swap()` once and proceed, regardless of whether the lock was acquired. Two processes could then both believe they hold the lock and enter their critical sections simultaneously, violating mutual exclusion.
Q50. What is the significance of the `n` variable in the bounded-waiting algorithm?
📖 Explanation: The variable `n` in the bounded-waiting algorithm represents the total number of processes (`P0` to `Pn-1`). It is used in the modulo operation during the cyclic scan of the `waiting` array, ensuring the scan wraps around correctly.
Q51. How does the use of hardware instructions like `compare and swap()` improve system efficiency compared to disabling interrupts?
📖 Explanation: Hardware instructions are local to each CPU. Unlike disabling interrupts, they do not require coordination with other processors. This makes them much more efficient for synchronization in multiprocessor systems, as there is no overhead of broadcasting messages, leading to better performance and scalability.
Q52. In the bounded-waiting algorithm, what is the initial value of `key` before the while loop?
📖 Explanation: Before entering the while loop, `key` is initialized to `true`. This forces the process to attempt to acquire the lock using `test and set()` at least once. If the lock is free, `test and set()` will return `false`, setting `key` to `false` and allowing the process to enter.
Q53. What is the purpose of the `j == i` check in the bounded-waiting algorithm's exit section?
📖 Explanation: The `j == i` check is used to determine if the cyclic scan of the `waiting` array has completed a full circle and returned to the starting process without finding any waiting process. If `j == i`, it means no other process is waiting, so the lock is released by setting `lock = false`.
Q54. What is the primary difference between the basic and advanced `test and set()` algorithms?
📖 Explanation: The key difference is the addition of the `waiting` array and the cyclic scan logic in the exit section. The basic algorithm simply sets `lock = false`, which could lead to starvation. The advanced algorithm uses the `waiting` array to track waiting processes and grants access in a fair, cyclic order, guaranteeing bounded waiting.