Skip to topic
    ← Back to course topics

    Thinking concurrently — OCR A-Level Computer Science

    Test yourself on Thinking concurrently with OCR A-Level practice questions.

    Start free

    7 days Premium · Then free forever · No card, no charge

    Thinking concurrently explained

    Thinking concurrently involves identifying parts of a problem that can be solved simultaneously to improve efficiency.

    Read the full explanation

    Learners must be able to outline the potential benefits and trade-offs associated with concurrent processing in specific scenarios.

    What to demonstrate

    1. Identification of tasks that can be executed in parallel
    2. Explanation of benefits of concurrent processing (e.g., reduced execution time)
    3. Explanation of trade-offs or challenges (e.g., overheads, synchronization, complexity)

    Thinking concurrently exam tips

    Topic Overview

    Thinking concurrently is a fundamental concept in computer science that involves designing and reasoning about systems where multiple processes or threads execute simultaneously. In the context of OCR A-Level Computer Science, this topic explores how concurrent execution can improve efficiency, responsiveness, and resource utilisation, but also introduces challenges such as race conditions, deadlocks, and starvation. Understanding concurrency is crucial for modern software development, as most systems—from smartphones to cloud servers—rely on concurrent processing to handle multiple tasks at once.

    This topic builds on earlier concepts of processes, threads, and scheduling, and is closely linked to the study of operating systems and parallel computing. Students will learn about the differences between concurrency and parallelism, the use of mutual exclusion and semaphores to manage shared resources, and the importance of deterministic and non-deterministic behaviour. Mastery of these ideas is essential for tackling more advanced topics like distributed systems and real-time computing, and for writing efficient, bug-free code in multi-threaded environments.

    In the OCR A-Level specification, thinking concurrently is assessed through both theoretical questions and practical programming tasks. Students must be able to analyse concurrent algorithms, identify potential issues, and implement solutions using appropriate synchronisation mechanisms. This topic also encourages computational thinking skills, particularly decomposition and abstraction, as students learn to break down complex problems into smaller, concurrent tasks.

    Key Concepts
    • →Concurrency vs. parallelism: Concurrency is about dealing with multiple tasks at once (interleaving), while parallelism is about executing multiple tasks simultaneously on multiple cores.
    • →Race conditions: Occur when two or more threads access shared data simultaneously, and the outcome depends on the order of execution. They can be prevented using mutual exclusion.
    • →Mutual exclusion and semaphores: Mutual exclusion ensures that only one thread accesses a critical section at a time. Semaphores are a synchronisation primitive that can control access to shared resources.
    • →Deadlock: A situation where two or more threads are each waiting for resources held by the other, causing them to stall indefinitely. Deadlock requires four conditions: mutual exclusion, hold and wait, no preemption, and circular wait.
    • →Deterministic vs. non-deterministic behaviour: Concurrent systems are often non-deterministic because the interleaving of threads can vary, leading to different outcomes. Understanding this is key to debugging and testing.
    Marking Points
    • Identification of tasks that can be executed in parallel
    • Explanation of benefits of concurrent processing (e.g., reduced execution time)
    • Explanation of trade-offs or challenges (e.g., overheads, synchronization, complexity)
    Examiner Tips
    • 💡Always relate the concept of concurrency to the specific problem context provided in the question
    • 💡Consider whether tasks are independent or if they require synchronization before proceeding
    • 💡Be prepared to discuss why some parts of a problem cannot be parallelized
    • 💡When answering questions about race conditions, always clearly identify the shared resource and the critical section. Explain how the race condition occurs and propose a specific synchronisation mechanism (e.g., a semaphore) to fix it.
    • 💡For deadlock questions, use the four conditions (mutual exclusion, hold and wait, no preemption, circular wait) to analyse whether a deadlock is possible. Then suggest a prevention method, such as imposing a total order on resource acquisition.
    • 💡In programming questions, ensure your code for mutual exclusion correctly initialises semaphores and uses wait() and signal() in the right places. Remember that semaphores can be binary or counting, and choose the appropriate type.
    Common Mistakes
    • Confusing concurrency with multitasking or parallel hardware without understanding the algorithmic decomposition
    • Failing to identify dependencies between tasks that prevent concurrent execution
    • Overlooking the overhead costs associated with managing concurrent threads or processes
    • Misconception: Concurrency always makes programs faster. Correction: Concurrency can improve responsiveness and resource utilisation, but overhead from context switching and synchronisation can actually slow down a program if not managed properly.
    • Misconception: Using more threads always increases performance. Correction: The optimal number of threads depends on the number of CPU cores and the nature of the task. Too many threads can lead to contention and reduced performance.
    • Misconception: A program that works correctly on one run will always work correctly. Correction: Due to non-determinism, concurrent programs may produce different results on different runs. Thorough testing and formal verification are needed.
    Frequently Asked Questions
    What is the difference between concurrency and parallelism?
    Concurrency is about dealing with multiple tasks at the same time, but not necessarily executing them simultaneously—tasks can be interleaved. Parallelism, on the other hand, requires multiple processing units (e.g., CPU cores) to execute multiple tasks at exactly the same time. Concurrency is a broader concept that includes parallelism, but you can have concurrency without parallelism (e.g., on a single-core system with time-slicing).
    How do you prevent race conditions in concurrent programming?
    Race conditions are prevented by ensuring mutual exclusion in critical sections—parts of code that access shared resources. This can be achieved using locks, semaphores, or monitors. For example, a binary semaphore can be used to protect a shared variable: each thread must wait() before entering the critical section and signal() after leaving. This ensures only one thread accesses the resource at a time, eliminating race conditions.
    What is a deadlock and how can it be avoided?
    A deadlock is a situation where two or more threads are each waiting for resources held by the other, causing them to stall indefinitely. Deadlock requires four conditions: mutual exclusion, hold and wait, no preemption, and circular wait. To avoid deadlock, you can prevent one of these conditions, e.g., by imposing a total order on resource acquisition (so threads always request resources in a fixed order) or by using a timeout mechanism.
    Why is concurrent programming non-deterministic?
    Concurrent programming is non-deterministic because the order in which threads execute is not fixed—it depends on the scheduler, system load, and other factors. This means that the interleaving of instructions can vary between runs, leading to different outcomes. For example, two threads incrementing a shared counter may produce different results depending on the timing of their reads and writes. This makes testing and debugging concurrent programs challenging.
    What is a semaphore and how does it work?
    A semaphore is a synchronisation primitive that controls access to a shared resource by multiple threads. It has a counter and two operations: wait() (also called P) and signal() (also called V). wait() decrements the counter; if the counter becomes negative, the thread is blocked. signal() increments the counter; if there are blocked threads, one is unblocked. Binary semaphores (counter 0 or 1) are used for mutual exclusion, while counting semaphores manage multiple resources.
    Can concurrent programs have bugs that only appear sometimes?
    Yes, this is a common issue due to non-determinism. Bugs like race conditions or deadlocks may only manifest under specific interleavings of thread execution, which might not occur during testing but happen in production. These are called 'heisenbugs' because they seem to disappear when you try to observe them. To catch them, use stress testing, formal verification, or tools like thread sanitizers.