C++ Concurrency Quiz

C++
0 Passed
0% acceptance

40 in-depth questions covering C++ concurrency with std::thread, thread synchronization, mutex types, condition variables, and race condition avoidance — with 16 code examples to solidify understanding.

40 Questions
~80 minutes
1

Question 1

What is the purpose of std::thread in C++?

A
To create and manage execution threads that run concurrently with the main thread, enabling parallel execution on multi-core systems
B
To create single-threaded programs
C
To stop program execution
D
To synchronize threads
2

Question 2

What is a race condition in concurrent programming?

cpp
int counter = 0;

void increment() {
    for (int i = 0; i < 1000; ++i) {
        counter++; // Race condition: not atomic
    }
}

// Two threads calling increment() may interleave
// Result: counter < 2000
A
When multiple threads access shared data concurrently without proper synchronization, leading to unpredictable results and data corruption
B
When threads execute too slowly
C
When threads finish execution
D
When threads are synchronized
3

Question 3

What is the purpose of std::mutex?

cpp
#include <mutex>

std::mutex mtx;
int counter = 0;

void increment() {
    std::lock_guard<std::mutex> lock(mtx);
    counter++; // Now thread-safe
}
A
To provide mutual exclusion for shared resources, ensuring only one thread can access protected code at a time
B
To create new threads
C
To stop threads
D
To share data between threads
4

Question 4

What is the difference between std::lock_guard and std::unique_lock?

cpp
std::mutex mtx;

void func1() {
    std::lock_guard<std::mutex> lock(mtx); // RAII, cannot unlock early
    // Critical section
} // Automatic unlock

void func2() {
    std::unique_lock<std::mutex> lock(mtx); // More flexible
    // Can unlock early
    lock.unlock();
    // Do something else
    lock.lock(); // Lock again
}
A
lock_guard provides simple RAII locking, unique_lock allows manual lock/unlock control and can be used with condition variables
B
They are identical classes
C
unique_lock is simpler than lock_guard
D
lock_guard allows manual control
5

Question 5

What is a deadlock in concurrent programming?

cpp
std::mutex mtx1, mtx2;

void thread1() {
    std::lock_guard<std::mutex> lock1(mtx1);
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    std::lock_guard<std::mutex> lock2(mtx2); // Deadlock!
}

void thread2() {
    std::lock_guard<std::mutex> lock2(mtx2);
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    std::lock_guard<std::mutex> lock1(mtx1); // Deadlock!
}
A
When two or more threads wait indefinitely for resources held by each other, causing program to freeze
B
When threads execute too quickly
C
When threads finish successfully
D
When threads are synchronized properly
6

Question 6

What is the purpose of condition variables?

cpp
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
std::queue<int> queue;

void producer() {
    std::unique_lock<std::mutex> lock(mtx);
    queue.push(42);
    cv.notify_one(); // Notify waiting thread
}

void consumer() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, []{ return !queue.empty(); }); // Wait for data
    int data = queue.front();
}
A
To synchronize threads based on state changes, allowing threads to wait for specific conditions and be notified when conditions are met
B
To create new threads
C
To stop threads
D
To share data directly
7

Question 7

What is the difference between join() and detach() in std::thread?

cpp
std::thread t(func);

t.join();    // Wait for thread to finish
// Thread resources cleaned up

std::thread t2(func);
t2.detach(); // Let thread run independently
// Thread continues, main thread doesn't wait
// Thread resources may not be cleaned up properly
A
join() waits for thread completion and cleans up resources, detach() allows thread to run independently but may leak resources if not managed properly
B
They are identical operations
C
detach() waits for completion
D
join() allows independent execution
8

Question 8

What is thread safety?

A
Guarantee that class or function can be used from multiple threads concurrently without causing data races or undefined behavior
B
Making threads run faster
C
Stopping threads
D
Creating single-threaded programs
9

Question 9

What is the purpose of std::atomic?

cpp
#include <atomic>

std::atomic<int> counter = 0;

void increment() {
    for (int i = 0; i < 1000; ++i) {
        counter++; // Atomic operation, no race condition
    }
}
A
To provide atomic operations on shared variables, ensuring operations complete without interruption and preventing data races
B
To create new threads
C
To synchronize threads
D
To stop atomic operations
10

Question 10

What is lock contention?

A
Performance degradation when multiple threads compete for the same lock, causing threads to wait and reducing parallelism
B
When locks work perfectly
C
When threads don't use locks
D
When locks are never acquired
11

Question 11

What is the difference between std::mutex and std::recursive_mutex?

cpp
std::mutex mtx;
void func() {
    std::lock_guard<std::mutex> lock(mtx);
    // Cannot call func() again - deadlock
}

std::recursive_mutex rmtx;
void recursive_func() {
    std::lock_guard<std::recursive_mutex> lock(rmtx);
    // Can call recursive_func() again - same thread
}
A
recursive_mutex allows same thread to lock multiple times, mutex prevents recursive locking and would deadlock
B
They are identical mutex types
C
mutex allows recursive locking
D
recursive_mutex prevents same thread locking
12

Question 12

What is thread local storage?

cpp
thread_local int counter = 0;

void increment() {
    counter++; // Each thread has its own counter
}

// Thread 1: counter = 1
// Thread 2: counter = 1 (separate variable)
A
Variables that have separate instances for each thread, avoiding the need for synchronization when each thread needs its own copy
B
Variables shared between all threads
C
Variables that cannot be accessed by threads
D
Variables that are destroyed immediately
13

Question 13

What is the purpose of std::call_once?

cpp
#include <mutex>

std::once_flag flag;
int* data = nullptr;

void init() {
    data = new int(42);
}

void thread_func() {
    std::call_once(flag, init); // init called only once
    // Use data safely
}
A
To ensure a function is called exactly once even when multiple threads attempt to call it simultaneously
B
To call functions multiple times
C
To prevent function calls
D
To call functions asynchronously
14

Question 14

What is the difference between spurious wakeup and lost wakeup?

cpp
std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void waiter() {
    std::unique_lock<std::mutex> lock(mtx);
    while (!ready) {  // Prevent spurious wakeup
        cv.wait(lock);
    }
}

void notifier() {
    {
        std::lock_guard<std::mutex> lock(mtx);
        ready = true;
    }
    cv.notify_one(); // Must be done while NOT holding lock
}
A
Spurious wakeup is when wait() returns without notification, lost wakeup is when notification happens before wait() is called
B
They are identical wakeup types
C
Spurious wakeup is expected behavior
D
Lost wakeup doesn't occur
15

Question 15

What is lock-free programming?

cpp
#include <atomic>

std::atomic<int> counter = 0;

void increment() {
    counter.fetch_add(1, std::memory_order_relaxed);
    // No locks, but atomic operations
}
A
Programming without mutexes using atomic operations and careful memory ordering to ensure thread safety without blocking
B
Programming that uses many locks
C
Programming that prevents concurrency
D
Programming that stops threads
16

Question 16

What is the difference between std::thread and std::jthread (C++20)?

cpp
std::thread t(func); // Must join or detach manually
t.join();

std::jthread jt(func); // Automatic join on destruction
// No manual join needed
A
jthread automatically joins on destruction preventing resource leaks, thread requires manual join/detach management
B
They are identical thread types
C
thread automatically joins
D
jthread requires manual management
17

Question 17

What is memory ordering in atomic operations?

cpp
std::atomic<int> x = 0, y = 0;

void thread1() {
    x.store(1, std::memory_order_relaxed);
    y.store(1, std::memory_order_release);
}

void thread2() {
    while (y.load(std::memory_order_acquire) != 1);
    assert(x.load(std::memory_order_relaxed) == 1); // May fail without proper ordering
}
A
Specification of how atomic operations synchronize memory between threads, controlling visibility and ordering of operations
B
Physical memory layout
C
Memory allocation order
D
Memory deallocation
18

Question 18

What is the difference between busy waiting and blocking synchronization?

cpp
// Busy waiting
bool ready = false;
void waiter() {
    while (!ready) { /* do nothing */ } // Wastes CPU
}

// Blocking synchronization
std::mutex mtx;
std::condition_variable cv;
void waiter() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, []{ return ready; }); // Sleeps until notified
}
A
Busy waiting wastes CPU checking condition repeatedly, blocking synchronization puts thread to sleep until condition is met
B
They are identical waiting strategies
C
Blocking synchronization wastes CPU
D
Busy waiting puts thread to sleep
19

Question 19

What is thread pool pattern?

cpp
class ThreadPool {
    std::vector<std::thread> workers;
    std::queue<std::function<void()>> tasks;
    std::mutex queue_mutex;
    std::condition_variable cv;
    
public:
    void enqueue(std::function<void()> task) {
        std::unique_lock<std::mutex> lock(queue_mutex);
        tasks.push(task);
        cv.notify_one();
    }
    
    // Worker threads continuously dequeue and execute tasks
};
A
Maintaining pool of reusable threads that execute queued tasks, avoiding thread creation/destruction overhead for frequent small tasks
B
Creating single thread for all tasks
C
Stopping all threads
D
Creating threads for each task
20

Question 20

What is the difference between data race and race condition?

A
Data race is low-level memory access conflict, race condition is higher-level logic error caused by timing-dependent behavior
B
They are identical concepts
C
Race condition is memory access conflict
D
Data race is logic error
21

Question 21

What is the purpose of std::shared_mutex?

cpp
#include <shared_mutex>

std::shared_mutex smtx;
int data = 0;

void reader() {
    std::shared_lock<std::shared_mutex> lock(smtx);
    // Multiple readers can read simultaneously
    int value = data;
}

void writer() {
    std::unique_lock<std::shared_mutex> lock(smtx);
    // Only one writer, no readers
    data = 42;
}
A
To allow multiple concurrent readers or single exclusive writer, optimizing read-heavy workloads compared to regular mutex
B
To prevent all concurrent access
C
To create single reader only
D
To allow multiple writers
22

Question 22

What is the difference between thread creation and thread spawning?

A
Thread creation refers to OS thread creation, thread spawning refers to creating threads from thread pool or other management system
B
They are identical processes
C
Thread spawning creates OS threads
D
Thread creation uses thread pools
23

Question 23

What is the purpose of std::promise and std::future?

cpp
#include <future>

std::promise<int> promise;
std::future<int> future = promise.get_future();

void producer() {
    int result = compute_value();
    promise.set_value(result);
}

void consumer() {
    int value = future.get(); // Blocks until promise fulfilled
}
A
To communicate values between threads, where promise produces value and future consumes it with synchronization
B
To create new threads
C
To stop threads
D
To synchronize without communication
24

Question 24

What is the difference between concurrent and parallel execution?

A
Concurrent execution interleaves execution on single core, parallel execution runs simultaneously on multiple cores
B
They are identical execution modes
C
Parallel execution interleaves on single core
D
Concurrent execution requires multiple cores
25

Question 25

What is the purpose of std::scoped_lock (C++17)?

cpp
std::mutex mtx1, mtx2;

void func() {
    std::scoped_lock lock(mtx1, mtx2); // Locks both atomically
    // No deadlock risk from lock ordering
}
A
To lock multiple mutexes simultaneously without deadlock risk, automatically determining correct lock order
B
To lock single mutex only
C
To unlock mutexes
D
To create deadlocks
26

Question 26

What is the difference between thread synchronization and thread communication?

A
Synchronization prevents concurrent access conflicts, communication passes data and signals between threads
B
They are identical concepts
C
Communication prevents access conflicts
D
Synchronization passes data
27

Question 27

What is the purpose of std::barrier (C++20)?

cpp
#include <barrier>

std::barrier barrier(3); // Wait for 3 threads

void worker() {
    do_work();
    barrier.arrive_and_wait(); // All threads sync here
    do_more_work();
}
A
To synchronize multiple threads at a common point, ensuring all threads reach barrier before any proceed
B
To stop threads
C
To create single thread
D
To prevent synchronization
28

Question 28

What is the difference between lock hierarchy and lock ordering?

A
Lock hierarchy defines mutex acquisition order by assigning levels, lock ordering is specific sequence used in code
B
They are identical deadlock prevention techniques
C
Lock ordering assigns levels
D
Lock hierarchy is code sequence
29

Question 29

What is the purpose of std::latch (C++20)?

cpp
#include <latch>

std::latch latch(1); // Start with count 1

void worker() {
    do_work();
    latch.count_down(); // Decrement count
}

void main_thread() {
    // Start workers
    latch.wait(); // Wait for count to reach 0
    // All workers done
}
A
To allow one thread to wait until counter reaches zero, useful for coordinating startup or completion of multiple operations
B
To create countdown timers
C
To stop threads immediately
D
To prevent thread coordination
30

Question 30

What is the difference between thread affinity and thread migration?

A
Thread affinity binds thread to specific CPU cores, thread migration allows OS to move threads between cores for load balancing
B
They are identical thread scheduling concepts
C
Thread migration binds to cores
D
Thread affinity allows migration
31

Question 31

What is the purpose of std::semaphore (C++20)?

cpp
#include <semaphore>

std::counting_semaphore<5> semaphore(3); // Max 3 concurrent

void worker() {
    semaphore.acquire(); // Wait for permit
    do_work();
    semaphore.release(); // Return permit
}
A
To limit number of threads accessing resource simultaneously, providing counting semaphore for resource management
B
To create unlimited threads
C
To stop all threads
D
To prevent resource access
32

Question 32

What is the difference between thread contention and thread starvation?

A
Contention is competition for resources causing delays, starvation is when thread never gets chance to run due to scheduling
B
They are identical performance issues
C
Starvation causes resource competition
D
Contention prevents thread execution
33

Question 33

What is the purpose of std::stop_token and std::stop_source (C++20)?

cpp
#include <stop_token>

std::stop_source source;

void worker(std::stop_token token) {
    while (!token.stop_requested()) {
        do_work();
        if (should_stop()) break;
    }
}

// Later...
source.request_stop(); // Signal all associated tokens
A
To provide cooperative cancellation mechanism where threads can check for stop requests and cleanup gracefully
B
To force thread termination
C
To prevent thread stopping
D
To create unstoppable threads
34

Question 34

What is the difference between thread priority and thread scheduling?

A
Thread priority influences scheduling order, thread scheduling is OS algorithm that determines which thread runs when
B
They are identical scheduling concepts
C
Thread scheduling sets priority
D
Thread priority determines scheduling algorithm
35

Question 35

What is the purpose of std::atomic_ref (C++20)?

cpp
#include <atomic>

int value = 0;
std::atomic_ref<int> atomic_value(value);

void increment() {
    atomic_value++; // Atomic operations on regular variable
}
A
To perform atomic operations on existing non-atomic variables without changing their type or layout
B
To create new atomic variables
C
To prevent atomic operations
D
To change variable types
36

Question 36

What is the difference between thread pool and thread spawning?

A
Thread pool reuses threads for multiple tasks, thread spawning creates new thread for each task with creation overhead
B
They are identical thread management approaches
C
Thread spawning reuses threads
D
Thread pool creates new threads
37

Question 37

What is the purpose of std::execution (C++17/20)?

cpp
#include <execution>
#include <algorithm>

std::vector<int> data = {3, 1, 4, 1, 5};
// Sequential sort
std::sort(data.begin(), data.end());

// Parallel sort (if available)
std::sort(std::execution::par, data.begin(), data.end());
A
To specify execution policy for parallel algorithms, allowing sequential, parallel, or vectorized execution
B
To stop algorithm execution
C
To create single-threaded execution
D
To prevent parallel execution
38

Question 38

What is the difference between thread cancellation and thread termination?

A
Cancellation is cooperative process where thread checks and responds to stop requests, termination is forceful stopping by OS
B
They are identical thread stopping methods
C
Termination is cooperative
D
Cancellation is forceful
39

Question 39

What is the purpose of std::hazard_pointer?

A
To safely delete objects in lock-free data structures by allowing threads to announce intent to access objects before deletion
B
To create dangerous pointers
C
To prevent object access
D
To force immediate deletion
40

Question 40

What are the fundamental principles for effective concurrency in C++?

A
Minimize shared state, use proper synchronization primitives, avoid deadlocks through lock ordering, prefer high-level abstractions, test for race conditions, and understand memory ordering
B
Never use concurrency in C++
C
Use as many threads as possible
D
Ignore synchronization for performance

QUIZZES IN C++