95: Multithreading. When Neither Side Budges.
Take Up Code - A podcast by Take Up Code: build your own computer games, apps, and robotics with podcasts and live classes
Categorie:
Deadlocks are another common problem with multithreading. I’ll explain how you can get into this situation and how to change your code to avoid the problem. This is a case where diagnosis is a lot harder than the cure. You have two options. Change how fine-grained your locks are by using fewer locks to encompass more resources. Keep the locks on individual resources and make sure to always acquire locks in the same order. I sometimes ask a question about deadlocks during interviews and have heard some creative answers over the years. You don’t need anything complicated to handle deadlocks. Just make sure to acquire locks in the same order. This works even if threads are asking for different numbers of locks. Let’s say that one thread wants to lock resources A, B, and C. And another thread only needs B and C. As long as both threads follow the same order for whatever locks they try to obtain, then you’ll avoid deadlocks. Listen to the full episode for more explanation, or you can also read the full transcript below. Transcript In the previous episode 94, I described how you can use critical sections to make sure that you have sole access to some variables when making changes. A critical section is really just a lock. And I even used the analogy of locking a room before changing a number written on a whiteboard. This works great. You can have many different locks available and all you need to do is remember to acquire the appropriate lock before making any changes. Proper multithreading requires that all the threads in a process follow the same rules. It won’t do you any good if most of your threads make sure to get locks while just one thread proceeds to modify objects as if it was the only thread remaining. But this brings up an interesting question. Why do you need multiple locks in the first place. Why not have only a single lock for everything? Have you ever went bowling. Your typical bowling alley has multiple lanes and when a group of people want to play, the group will have sole access to their lane for a couple hours. Imagine the confusion that would result if anybody was allowed to grab a ball and throw it down any lane at any time. You could think of this as if the group of people locked their lane while they’re using it. This works out well for the bowling alley because each lane can be locked separately for different teams. Individual locks allow your code to be more fine-grained whenever multiple resources are involved. Your code only needs to lock what it wants to change. The alternative would be for the bowling alley to lock their main doors and not let anybody else enter the whole building while a team occupies just one lane. This is a waste because normally resources like this can act independently of each other. Whenever you have multiple variables, or objects, or anything that needs multithreaded access control, you need to decide which are independent. Then you create a lock for each of these independent pieces. Just like how the bowling alley allows each lane to be locked while in use. If this was the whole story, then there wouldn’t be any deadlocks. Sometimes though you might need to do something that requires more than just one lock. Let’s say you gather a large group of friends to go bowling and need two lanes. This is where you can run into problems. Just that simple extra requirement to get multiple locks can bring your whole application to a complete stop. Have you ever used an application on your computer when it just froze? It just stopped working? Well, that in itself doesn’t mean there was a deadlock. But that’s the kind of devastation that deadlocks can bring down on your application. I’ll describe what causes a deadlock and how you can avoid them right after this message from our sponsor. ( Message from Sponsor ) Okay, you need two lanes now at the bowling alley. To simplify things, let’s pretend this is a really small b