1

You can say this is opinion based, but the problem is that everyone's opinion on this issue is same.

Even the lead developers say that creating the threads is easy, dealing with them together is difficult. It isn't a newbie's job.

All I know is that to deal with threads you have to lock all shared data till each thread finishes accessing it on its own (rather than getting interrupted by kernel), and then unlock it.

That will solve all deadlocks and race conditions. Won't it?

What point am I missing here?

CoffeeDay
  • 137

4 Answers4

13

Concurrent programming is difficult, notably because you need to deal with synchronization issues.

All I know is that to deal with threads you have to lock all shared data till each thread finishes accessing it on its own (rather than getting interrupted by kernel), and then unlock it.

You don't know enough about threads. Read some POSIX thread tutorial. You not only need to use mutexes, but you should avoid deadlocks, and you probably need condition variables.

And in practice, finding good trade-offs is difficult (see the table here to grasp the typical timings of operations). Locking granularity matters a lot (you probably don't want to lock & unlock some mutex every two lines).

At the hardware level, cache coherence is important in multi-core processors, and memory models, memory ordering are difficult to understand. In practice, a multi-core system does not behave "intuitively" w.r.t. time (in other words, each core might have its own notion of time & clock).

4

As usual, there is a trade-off involved. Doing everything in one thread is simple and risk-free. Doing things in multiple threads increases performance, but introduces risk of consistency errors. Using locks to guard against such errors can negate the entire performance advantage for which you introduced threads in the first place.

In other words, maintainability, performance and correctness form a triad of requirements, of which only two are easy to fulfill simultaneously. There is a reason why so many alternative concurrency models are being floated nowadays; the problem is only going to become more pressing in the future, because CPUs don't get faster anymore, just more parallel, and the average programmer isn't up to making productive use of them with our existing models.

Kilian Foth
  • 110,899
3

Locking objects can be the cause of deadlocks if you're not careful. Suppose you have two data structures A and B that need to have data in them synchronised. Thread 1 updates A with new information, then updates B to match. Thread 2 updates B with new information, then updates A to match.

So the workflow for thread 1 might be:

 1. Receive new data.
 2. Lock A.
 3. Update A.
 4. Lock B.
 5. Update B to match.
 6. Unlock B.
 7. Unlock A.
 8. Goto 1.

Note that we have A and B locked at the same time so somebody else doesn't modify B until we've got our changes synchronized across the two.

Suppose threads 1 and 2 both receive new information at the same time and need to update the data structures. The order in which things could happen is totally unpredictable, but it could be:

 1. Thread 1 locks A
 2. Thread 1 updates A
 3. Thread 2 locks B
 4. Thread 2 updates B
 5. Thread 1 now needs to update B, so it tries to lock B.  B is already locked so it waits.
 6. Thread 2 now needs to update A, so it tries to lock A.  A is already locked so it waits.
 7. Oops - deadlock.  The whole program is now permanently stuck.
Simon B
  • 9,772
3

lock all shared data till each thread finishes accessing it on its own

This is the difficult bit. You have to correctly identify all places in the software where shared data is accessed. You then have to apply locks at the correct scope level: if you have too much locked, then only one thread will be able to proceed (e.g. Python's global interpreter lock, GIL). If you lock/unlock too frequently, that will slow down the program.

Often you will find some parts of the architecture that are highly contended. Then you end up redesigning large areas of the system to reduce that contention.

pjc50
  • 15,223