1/55
Looks like no tags are added yet.
Name | Mastery | Learn | Test | Matching | Spaced | Call with Kai |
|---|
No analytics yet
Send a link to your students to track their progress
How does a generalized Readers-Writers lock handle multiple processes requesting read access?
Multiple processes can acquire in read mode.
[Explain]: Describe how the `preempt_count` mechanism in Linux ensures kernel non-preemption when a task holds a lock, and what condition allows for safe kernel preemption.
Each task in the Linux kernel has a `thread-info` structure containing a `preempt_count`. This counter is incremented when a task acquires a lock and decremented when it releases it. The kernel is designed to be non-preemptible if a task running in the kernel is holding any lock. Therefore, if the `preempt_count` for the currently running task is greater than 0, it signifies that the task is within a critical section (holding a lock) and it is not safe to preempt the kernel. Conversely, if the `preempt_count` is 0, it indicates that the task is not holding any locks, and the kernel can safely be interrupted to run another task.
[Compare]: Explain the fundamental differences between mutex locks and spinlocks in the Linux kernel, focusing on their suitability for different scenarios and their behavior when a lock is contended.
Mutex locks are suitable for protecting critical sections that may require longer lock holding times. When a mutex is contended (i.e., unavailable), the task attempting to acquire it is put into a sleep state and awakened later. This allows other tasks to run. Spinlocks, on the other hand, are preferred for very short critical sections, especially on Symmetric Multiprocessing (SMP) machines. If a spinlock is contended, the task attempting to acquire it will spin (repeatedly check if the lock is available) without yielding the CPU. On single-processor systems, spinlocks are replaced by disabling and enabling kernel preemption. The key difference lies in how contention is handled: mutexes involve sleeping, while spinlocks involve busy-waiting (spinning) or disabling preemption.
What is the primary risk in a Dining-Philosophers solution that successfully prevents deadlock but does not manage fair resource distribution?
Philosopher starvation
What is the fundamental trade-off illustrated by the two basic Readers-Writers problems?
Reader starvation versus writer starvation.
Which strategy ensures a philosopher avoids partial resource acquisition in the Dining-Philosophers problem?
Acquiring both chopsticks simultaneously
What is the fundamental requirement for a writer thread accessing a shared database in the Readers-Writers Problem?
Writers must have exclusive access.
In an asymmetric solution to the Dining-Philosophers problem, how do even-numbered and odd-numbered philosophers differ in their behavior?
They start with different chopsticks
In the bounded-buffer problem, what must happen when the producer detects that the buffer has reached its maximum capacity?
The producer must stop adding data until space becomes available
What is the primary purpose of a generalized Readers-Writers lock in managing shared resources?
To balance concurrent read and exclusive write access.
In the Linux kernel, for which scenario are atomic integers generally preferred over mutex locks?
Updating a simple shared counter
[Explain]: Why would a Linux kernel developer choose an atomic_t integer over a mutex lock for a simple shared counter, and what are the limitations of this choice?
A developer would choose atomic_t because it performs mathematical operations atomically without the overhead of locking mechanisms (like context switching or sleeping), making it highly efficient for simple updates. However, the limitation is that atomic integers are only suitable for simple shared variables like counters or flags; they cannot protect complex critical sections or multiple related data structures that require mutual exclusion.
Why are spinlocks considered inappropriate for use on single-processor systems in Linux?
They waste CPU cycles spinning
What happens to a Linux task that calls mutex_lock() when the requested lock is already held by another task?
The task enters a sleep state
What happens if a thread in the Linux kernel attempts to acquire a mutex lock it already possesses?
The thread enters a deadlock state
Which Linux synchronization mechanism is specifically designed to allow multiple readers but only one writer to access a resource?
Reader-writer versions of locks
In the context of the second Readers-Writers Problem, what action is taken when a writer is ready to access the shared object?
No new readers may start reading.
How does limiting the number of philosophers at the table to four instead of five prevent deadlock?
It breaks the circular wait
[Compare]: Contrast the 'First' and 'Second' variations of the Readers-Writers problem in terms of their prioritization and the specific type of starvation they risk.
The First variation prioritizes readers: no reader is kept waiting unless a writer has already secured the lock. This risks writer starvation if a steady stream of readers keeps the resource busy. The Second variation prioritizes writers: once a writer is ready, no new readers can start. This risks reader starvation if writers arrive continuously. Both demonstrate a trade-off between throughput for one group and fairness for the other.
In the Dining-Philosophers problem, what specific condition occurs if every philosopher simultaneously picks up their left chopstick and waits for their right chopstick?
A state of deadlock
[Quick Exercise]: In the Dining-Philosophers problem, five philosophers sit in a circle with one chopstick between each pair. Propose three distinct strategies to prevent a deadlock where every philosopher holds one chopstick and waits forever for the second.
1. Limit Concurrency: Allow only four philosophers at the table simultaneously so at least one can always acquire two chopsticks. 2. Simultaneous Acquisition: Require a philosopher to pick up chopsticks only if both are available (atomic acquisition). 3. Asymmetric Ordering: Assign an order to resources, such as odd-numbered philosophers picking up the left chopstick first and even-numbered ones picking up the right first, breaking the circular wait.
What is the primary risk of the first Readers-Writers Problem, which prioritizes reader access?
Writer starvation.
Why are atomic_t integers in the Linux kernel more efficient than mutexes for updating a simple shared counter?
They avoid locking overhead
What is the primary function of a mutex lock associated with a condition variable in a multithreaded program?
To protect shared data from concurrent access and ensure atomic condition checks.
Which data type is used for condition variables in Pthreads, and what must it be associated with for thread-safe operation?
pthread_cond_t associated with a mutex lock
When a thread returns from a pthread_cond_wait() call after being signaled, what is its relationship to the associated mutex?
It becomes the owner of the mutex lock.
What happens to the associated mutex lock when a thread calls pthread_cond_wait() because a condition is not met?
The mutex is automatically released by the function.
Which specific data type is defined by the Pthreads library to represent a mutex lock?
pthread_mutex_t
What fundamental characteristic of functional programming paradigms prevents the occurrence of race conditions and deadlocks during concurrent execution?
The enforcement of immutable state
[Compare]: Contrast Software Transactional Memory (STM) and Hardware Transactional Memory (HTM) in terms of implementation and performance overhead.
STM is implemented entirely in software, which requires code instrumentation and typically results in higher overhead. HTM utilizes existing hardware cache hierarchies and coherency protocols to manage conflicts. Because HTM requires no special software instrumentation, it incurs significantly less overhead than STM, though it requires specific hardware support.
Which statement accurately describes the origin of POSIX semaphores?
POSIX semaphores are defined within the POSIX SEM extension.
Which function must be called by the owner of a mutex to allow other blocked threads to acquire it?
pthread_mutex_unlock()
How does transactional memory prevent deadlocks?
By the system managing atomicity, allowing concurrent operations within atomic blocks.
What are the two primary types of POSIX semaphores?
Named and unnamed semaphores.
[Explain]: How does OpenMP allow a programmer to parallelize a standard C++ 'for' loop with minimal changes to the source code, and what mechanism does it use to communicate with the compiler?
OpenMP uses 'pragmas', which are special compiler directives. By adding a pragma (such as #pragma omp parallel for) above a loop, the programmer instructs the compiler to handle the creation of threads and the distribution of iterations. This abstracts the underlying complexity of thread management, allowing the original logic to remain largely unchanged.
What is the primary advantage of using immutable state in functional programming languages?
It simplifies debugging by eliminating side effects related to state changes.
What occurs when a thread attempts to call pthread_mutex_lock() on a mutex that is currently held by another thread?
The calling thread is blocked until the lock is released.
[Quick Exercise]: A thread needs to update a shared counter using Pthreads. Sequence the following operations correctly to ensure thread safety and explain what happens if the second operation is called while another thread holds the lock: pthread_mutex_unlock(), pthread_mutex_init(), pthread_mutex_lock().
The correct sequence is: 1. pthread_mutex_init() (initialization), 2. pthread_mutex_lock() (acquisition), 3. pthread_mutex_unlock() (release). If pthread_mutex_lock() is called while another thread holds the lock, the calling thread is blocked (suspended) until the owner calls pthread_mutex_unlock(). All these functions return 0 upon successful completion.
In OpenMP, who is responsible for creating and managing threads?
The OpenMP library handles thread creation and management.
What is a key difference between Software Transactional Memory (STM) and Hardware Transactional Memory (HTM)?
STM requires special code instrumentation, while HTM does not.
What is the standard function used to initialize a mutex lock in a Pthreads-based application?
pthread_mutex_init()
After a thread calls pthread_cond_signal() to wake a waiting thread, what action must it take to allow the signaled thread to proceed?
It must explicitly call pthread_mutex_unlock().
[Explain]: In Pthreads, why must a condition variable (pthread_cond_t) always be associated with a mutex (pthread_mutex_t), and what is the specific atomic behavior of pthread_cond_wait() regarding that mutex?
The mutex protects the shared data (the state) that the condition variable is testing. pthread_cond_wait() performs a critical atomic operation: it releases the mutex and puts the thread to sleep simultaneously. This allows other threads to acquire the mutex and change the state. When the thread is signaled and wakes up, it automatically re-acquires the mutex before returning, ensuring exclusive access to the shared data.
What are the standard POSIX functions for performing wait and signal operations on semaphores?
sem_wait() and sem_post()
What is a key advantage of using transactional memory for thread synchronization compared to traditional locks?
It guarantees atomicity without requiring the programmer to implement locking logic.
What is the return value of Pthreads mutex functions, such as lock and unlock, when they operate correctly?
A value of 0
What function is used to initialize unnamed POSIX semaphores?
sem_init()
What is a memory transaction in the context of thread synchronization?
A sequence of read-write operations that either all succeed or all fail and roll back.
What is the primary purpose of OpenMP?
To provide a framework for creating concurrent programs.
How does immutability in functional programming languages contribute to the absence of race conditions and deadlocks?
By preventing multiple threads from interfering with each other's data.
What is a key feature of functional programming languages that helps avoid concurrency issues?
The enforcement of immutable state.
[Compare]: Contrast POSIX named and unnamed semaphores in terms of their initialization, scope of use, and portability within the POSIX environment.
Named semaphores are created via sem_open() using a string name, allowing unrelated processes to synchronize. Unnamed semaphores are initialized via sem_init() and are typically used for thread-level synchronization within a single process. Both belong to the POSIX SEM extension rather than the base standard, meaning they may not be available on all POSIX-compliant systems.
How does OpenMP facilitate parallel programming in C/C++?
By using pragmas, which are compiler directives, to specify parallel regions and loops.
How do unrelated processes typically share a common semaphore using the POSIX SEM extension?
By using sem_open() with a unique system-wide name.
[Explain]: How does the mechanism of transactional memory ensure data consistency differently than traditional locking mechanisms like semaphores?
Transactional memory treats a sequence of read-write operations as a single atomic transaction. Unlike semaphores, which require the programmer to manually manage sem_wait() and sem_post() to prevent race conditions, transactional memory shifts the responsibility to the system. If all operations in a transaction succeed, they commit; if a conflict occurs, the system automatically rolls back the changes, ensuring the programmer does not have to manually handle complex lock management or deadlocks.
[Case Study]: A developer is choosing between an imperative language (like C++) and a functional language (like Erlang) for a highly concurrent system. How does the handling of 'state' in these paradigms affect the risk of race conditions and deadlocks?
Imperative languages are state-based and allow mutable variables, requiring manual synchronization (like locks) to prevent race conditions, which introduces the risk of deadlocks. Functional languages enforce immutability; once a value is assigned, it cannot change. Because there is no mutable state to compete for, race conditions and deadlocks are inherently eliminated by the language design.