-1

I understand in a single core system, multiple threads operate in sequence, scheduled by the OS. Hence it can't be possible to have a race condition since by definition they are taking turns locking a variable.

However if I have a multicore processor, is it possible for multiple threads of the same process to be run concurrently and hence both attempt to lock a variable at the same time?

For example I have a global semaphore s = 1

If 2 threads on different cores ran simultaneously, they both would try to decrement the semaphore and be successful in race conditions.

In a single core, 2 threads operate in sequence (scheduled by OS), so this is not possible, as the second thread will see s = 0 by the time it is scheduled.

Therefore I'm wondering if I have a process that spawns multiple threads, and I have multiple cores, what is stopping the race condition where 2 threads running simultaneously see the global semaphore as s=1 at the same time and attempt to operate on it?

3

1 Answer 1

2

I understand in a single core system, multiple threads operate in sequence, scheduled by the OS.

They do, though there are two potential kinds of threading models, which go do the nature of the "turn" or slice of the CPU offered to a thread by the operating system: cooperative and interrupted — the former requires the programmer to periodically yield, and the latter uses the CPU clock and other I/O device interrupts to determine what code to run next.

Most modern operating systems offer interrupted threads rather than cooperative threads — they work better for very independent workloads, and work better on multi-cpu architectures as well, and so I'll not discuss cooperative threads further.

Hence it can't be possible to have a race condition since by definition they are taking turns locking a variable.

This is generally not the case since with modern threads, the granularity of potential interruption is very small: between any two machine code instructions.  Because of this, these threads are still subject to race conditions, since many operations we might consider in a high level language expand to multiple machine instructions.

Then, for interdependent threads — i.e. working on the same in-memory data structures, single cpu or multi-cpu — the threads should announce when they are starting to work on shared data that could lead to a race.  To accomplish this, the hardware guarantees that some minimum primitive operations are atomic (performed atomically — or aborted) across all CPUs and the software uses these hardware features to compose larger critical sections, locks, and/or transactions.


See for example, the MESI protocol, which is a mechanism by which CPU's use their caches to communicate the status of these primitive operations.

1
  • To add, those atomic options are provided by the OS's APIs, so use them rather than attempting to roll your own. Sep 13, 2018 at 4:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.