Multithread & Async Development Flashcards
(33 cards)
What is a “timeslice”?
The CPU Thread Scheduler gives each ready-to-run thread a very small, fixed amount of CPU time, called a “time slice” or “quantum.” When a thread’s time slice expires, the scheduler interrupts it and quickly switches the CPU to another waiting thread. This rapid switching happens so fast (thousands of times per second) that it creates the illusion of concurrent or simultaneous execution, allowing multiple programs and tasks to appear to run at the same time, ensuring fairness and responsiveness across all active applications.
Explain the relationship between the CPU, Thread Scheduler, and Process/Application
The Process/Application contains Threads, and these Threads are the units of work that the Thread Scheduler assigns to the CPU for execution
What is “Divide and Conquer” in multi-threading applications, and why is it useful?
It is for breaking down problems into multiple smaller, independent sub-problems. Each of these smaller sub-problems can then be assigned to a separate thread to be solved concurrently (at the same time).
Once all the threads complete their individual tasks, their results are combined to produce the final solution to the original large problem.
what is the below code called and what does it do?
lock(…) { … }
It is called an Exclusive Lock.
It creates a critical section of code, meaning it ensures that only one thread can execute the code block within the lock statement at any given time. If another thread tries to enter the same lock block while it’s already locked, that thread will be blocked (paused) until the first thread exits the block and releases the lock.
Its primary purpose is to prevent race conditions and ensure thread safety when multiple threads try to access or modify shared resources (like a shared variable, a list, or a database connection) simultaneously, which could otherwise lead to incorrect or unpredictable results.
What does lock(…) { … } compile to?
Monitor.Enter(lockObject);
try
{
// your code here
}
finally
{
Monitor.Exit(lockObject);
}
Why is Task.Run(() => {}) preferred over new Thread(() => {}).Start()
Task.Run(() => {}) leverages the .NET Thread Pool, which is a highly optimized pool of reusable threads managed by the runtime. Task.Run() efficiently reuses existing threads from the thread pool, avoiding the cost of creating new ones.
What are reasons why an application might have multiple processes instead of just one?
Security: The isolation between processes acts as a strong security boundary.
Resource Management: It can be easier to monitor and manage resource consumption (CPU, memory) for individual components when they run in separate processes - like how modern browsers work.
In C#, what is a Mutex, and why use one?
A Mutex (Mutual Exclusion) is a synchronization primitive that grants exclusive access to a shared resource to only one thread at a time. Use it to prevent race conditions and ensure thread safety when multiple threads access shared data or resources.
Why use a Mutex over lock/Monitor?
Mutexes can be used for inter-process synchronization (across different processes), while lock/Monitor are for intra-process (within the same process) synchronization. Mutexes can also be named system-wide.
What are “Reader” and “Writer” locks?
Reader/Writer locks (ReaderWriterLockSlim in C#) allow multiple “reader” threads concurrent access to a resource while granting exclusive access to a single “writer” thread. This optimizes performance when reads far outnumber writes.
Why use Reader/Writer locks over lock/Monitor?
Reader/Writer locks offer better concurrency than simple locks when there are many more reads than writes. Simple locks (lock/Monitor) block all other threads, even readers, during any access, which can reduce performance in read-heavy scenarios.
How does a Reader/Writer Lock keep the resource synchronized?
When a resource is under a reader lock, multiple readers can access it simultaneously. This lock specifically prevents writers from making changes.
In contrast, a writer lock provides exclusive control, meaning no other readers or writers can access the resource until the writer is finished.
What is a Semaphore and how do they work?
A Semaphore controls access to a limited pool of resources. It maintains a count of available resources. Threads request a resource (decrement count); if unavailable, they wait. When a thread releases a resource (increment count), a waiting thread can acquire it.
What is a reason to use the Semaphore?
You can release locks in different threads. An example would be: using semaphore.Wait() in one thread, spinning off another thread and allowing the thread that spun off to .Release() the semaphore.
semaphore.Wait()
new Thread(() => someProcess).Start();
void someProcess
{
// do some work
semaphore.Release();
}
What is Thread Affinity?
Thread affinity is the concept where a task or operation prefers or requires execution on a specific thread or a set of threads, often due to reliance on thread-local state or UI components tied to a particular thread.
What is the Threads window in Visual Studio and what is it used for?
The Threads window in Visual Studio is a debugging tool that lists all active threads in your application. It allows you to inspect each thread’s ID, name, location, priority, and state, as well as switch between threads for focused debugging
What is the Parallel Stacks window in Visual Studio and what is it used for?
The Parallel Stacks window in Visual Studio is a debugging tool for multithreaded applications. It visually displays call stack information for all threads (or tasks) in the application, helping you understand their relationships, identify deadlocks, and analyze performance issues in parallel code.
How can you log the id of the current thread in Visual Studio?
Pause the application (this will pause all the threads) and in the Immediate Window, you can write Thread.CurrentThread.ManagedThreadId; and hit enter, and it will log out the current thread that the debugger is focused on.
How do you return a result from a thread?
With basic threads, the only way to return a result is by using shared variables. Otherwise, you’ll have to use a Task with a TResult.
How do call stacks when using multiple threads?
Each thread has its own independent call stack. When debugging, you can view the call stack for the currently selected thread in the “Call Stack” window. The “Parallel Stacks” window shows all threads’ call stacks simultaneously.
How do you handle exceptions that occur inside a thread?
You have to handle the exception inside the thread. If the exception bubbles its way outside the thread, it will break the application regardless if it’s wrapped by a trycatch in the application thread.
What is the difference between multi-threaded programming and async programming in c#?
Multi-threading uses multiple threads to execute code concurrently and explicitly uses threads.
Though async/await programming uses managed threads behind the scenes, its primary purpose is to perform non-blocking I/O operations, with an emphasis of offloading long long running tasks.
What is the difference between a Task and a Thread?
A Thread is an OS-level construct representing an execution path. A Task is a higher-level abstraction over an operation that can run asynchronously. Tasks are often executed on a thread pool, abstracting thread management away from the developer.
When an exception occurs in a task, what happens to the task and what happens to the application?
When an exception occurs in a Task, the exception is stored within the Task itself and the Task transitions to a faulted state. The application generally doesn’t crash immediately unless the exception is explicitly rethrown when the task’s result is accessed or the task is awaited.