3

When programming using (pre-emptive) multithreading model on a single processor, we need to deal with synchronization, deadlocks, etc. Do any additional concerns appear (and correspondingly, new techniques used) when switching to multithreading on multiple processors?

1

2 Answers 2

3

Fundamentally, the other issue is cache consistency. Threads that use memory to communicate have potential issues with modern architectures.

A single core processor only has one cache, and so it is always consistent, meaning that there are only the usual race conditions and deadlocks (around locking) for sharing information between threads via memory.

A multi core processor typically has separate cache areas for each cpu. That means that there is some potential for the different cpu's caches to be inconsistent, which is a another area for problems in sharing information between threads; this goes by the topic of memory models.

x86 and x64 have very strong memory models, so are forgiving to programmers who forget to declare volatile or use proper fences and/or barriers (say, as required by C/C++ standards). (FYI, a strong memory model takes work to implement and as such increases power consumption and hurts performance.)

Other hardware architectures (especially RISC architectures, like MIPS, others) with multi core rely more on software doing the right thing for maintaining cache consistency; software must use fences and barriers to communicate what about constantly changing memory is important between cpus.

Sometimes weak memory model issues are hidden by higher level software, such as the Java or C# runtime, but this area is sadly complex and there are often subtle bugs in algorithms.

The concept of memory model goes to what the processor must reload in the cache by re-sourcing from main memory when it sees certain conditions. If all conditions cause cache reloads that slows down the processors and often for no helpful reason from a software perspective. The problem is to decide what memory modifications are significant to be shared with other cpus and what aren't; hence differing architectures make different trade offs.


As an aside, on a custom embedded systems using as single core, you can create the capability to determine if it has been interrupted within a series of instructions (say by keeping an interrupt count and capture on start and compare on end, or maybe just by turning off interrupts instead). If it hasn't been interrupted within a series of instructions, software can make the assumption that it has functioned atomically. These techniques don't work (they doesn't give use the same guarantees) on multi-core processors.

0
1

The problem that locks solve is not caused by multiprocessing (i.e. two threads executing simultaneously on different cores), but by a lack of atomicity.

So when we say:

lock (lockObject)
{
    // This code is atomic...
}

... because any thread entering that critical section has to wait until the current thread is done executing. This is true whether or not multiple cores are in play.

Multi-processing is faithfully simulated on a single-core machine with hardware interrupts. When multiple cores are used, no new problems arise that aren't already solved with the usual concurrency techniques.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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