
Jonathan C. answered 08/16/19
Programmer
Concurrency is just running multiple tasks over the same span of time. Even old operating systems designed for a single CPU could do basic concurrency, having multiple programs 'active' over a time period, but only running instructions for one program at a time. The OS could swap between different tasks fast enough and it would seem that they are running at the same time, however, in this system, all instructions are running in serial (One after another) rather than in parallel.
Parallelism refers to specifically, in the same time slice, actually running multiple instructions for multiple programs in the same timestep. Modern multicore processors actually have parallelism. GPUs are highly parrallelized, as there are tons of separate cores running instructions in parallel.
Demonstrating these principles:
Say we need to run the following tasks, which take the following amount of 'work':
A: 3 B: 5 C: 2
If a 'single-core' system runs these concurrently, a schedule of running these tasks might look like:
(Each appearance of each letter is one time slice, see how each appears once.
CPU1: A-A-A-B-B-B-B-B-C-C
This is running them without any concurrency, each task is completed before moving on to the next.
It takes a total of 10 units of 'work'.
CPU1: A-B-C-B-A-B-C-B-A-B
This is running them concurrently, and still takes 10 units of 'work', however long those take.
However, each task shares the CPU, rather than like the original model, where each task gets the entire CPU until it completes.
If we add a second CPU to run things in parallel, that might look like:
CPU1: A-A-A-C-C
CPU2: B-B-B-B-B
This is simply running things in parallel (note how, like the original example, each task runs until complete)
And note, that now the tasks have finished in 5 units of 'work', rather than 10. Since we can 'double up' and run two tasks at the same time, we can complete all of the tasks faster.
Parallelism has limits, however, in the same example, even if we had more CPUs then this, (assuming each step in each task itself must run serially, which is typically how most real world problems eventually break down) we cannot possibly shave any more time off the requirement.
(in this example, I means that CPU is idle for that time step)
CPU1: A-A-A-I-I
CPU2: B-B-B-B-B
CPU3: C-C-I-I-I
CPU4: I-I-I-I-I
(And any other additional CPUs, in this example, would be like CPU4, Idle the entire time)
Now, you may be asking, what is the benefit of concurrency, if there is no speed up like with parallelism?
Concurrency allows a computer system to maintain responsiveness when it is busy. Concurrency is what allows you to still use a system for other things when doing some expensive task (for example, rendering a video or unpacking a large compressed archive). It allows the OS input handler to swap in and allow the system to respond to you moving the mouse or typing keys while another program is busy in a loop.