Jump to content
  • Advertisement
Sign in to follow this  
svetpet

Multithreading questions

This topic is 428 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, i have some questions regarding the multithreaded development

1. Lets have 2 threads that are accessing a queue, which is protected by mutex.

Is it necessary to use the same mutex or we can use one mutex for one thread and another mutex for the other thread?

If both threads are trying to access the queue, which is protected by one mutex, what happens? Does one of the threads blocks until the mutex is unlocked or the resource is directly accessed by both threads (which I think leads to data race)? If one of the threads is block, while waiting for the mutex can't we use 2 different mutexes, which would lead to the same result (not very practical, though).

2. We have one thread that is protecting a queue by mutex

What happens if we use second mutex to protect the queue, while the first mutex is already locked? Is this meaningful at all?

Generally my questions is do we always have to use only one mutex to protect single resource or we can use other mutexes?

 

Share this post


Link to post
Share on other sites
Advertisement

Note that simultaneously locking multiple mutexes for any reason can lead to deadlock if you are not extremely careful. When it is necessary to lock multiple mutexes for some operation, there is a common pattern called locking order which is employed to defend against deadlocks.

Share this post


Link to post
Share on other sites

Let's go back one step, why do we have mutexes?

As an example, let's say you have two variables "a", and "b". For some reason (I'll get to that at the end), both a and b must always both be updated, or it crashes. With a single thread, this is trivial. You always first update a and then you update b.

When you have 2 or more threads, this becomes a mess. Several processes all update a and b, each in their own speed, possibly overwriting each other results, and in any case, some of the updates get lost, a and b get out of sync, and stuff crashes.

(I ihope you can see that problem, if not, I'd suggest you look into that first, as it's the core problem of multi-threading.)

 

Ok, so just updating a and b with multiple threads doesn't work, now what? This is where a  mutex comes in. Basically, a single mutex is two guards. One guard is an entry guard named "claim", the other guard is an exit guard named "release". The rule is that all threads first have to pass the entry guard, then they change a and b in the way they want, and then they exit through the exit guard. The guards make sure that only one thread can have entered without having exited. Also, threads may not touch a and b at any other spot then between the entry and the exit guards.

As a thread, it means that if you want to update a and b, you must first pass the entry guard, change a and b, and then pass the exit guard to allow other threads access to the a and b variables. Both guards ensure that at most one thread can change a and b, that is, the small area where you change a and b acts like the single threaded update, in a world surrounded by mullti-threading. See it as a sound-proof room in a busy city. The room has a guard, and allows only one person at a time in. A place for quietness and pondering without getting disturbed by the other parts of the world that surround you. When you're done, you leave the room again for the next person.

Your question now translates to "what would happen if we add more different entry and exit guards?" (or "what happens if we add more doors to the quiet room?"). The short answer is "chaos", since we're back to square one. We started with the observation that having multiple threads updating a and b at the same time will crash. We invented this guard system to ensure only one thread can access a and b. When you add more entry and exit guards, you're back at the situation where several threads can update a and b at the same time, ie you're back at missing updates and getting crashes.

So this is why having a single mutex that is shared between all mutexes is crucial. Even if you have 5 places in the code that update a and b, if all those places use the same entry and exit guard, there is at most 1 place being used at any time, and the thread that is in that place can be sure nobody else is messing around with variables a and b until it leaves through the exit guard.

 

Finally, how does a and b relate to real-world things like queues? If you look closely at a queue, it has two parts. One part is the actually queued message (variable a), and one part is the administration of where to find the entries (variable b). This pretty much holds for anything, even a single integer variable can be seen like that. If you want to add a value to an integer, you first have to read the old value (part a), then compute the sum, and then write the new value (part b). That is, sometimes variables a and b are the same thing.

The latter is however not the best solution. Things like updating a single variable are so common that processors have a few dedicated instructions to do that safely in a multi-threaded environment. It's like a special case entry-exit mutex built into the processor. This only works for simple variables and a few simple operations though, objects and data structures like queues always need mutexes for safe working.

Share this post


Link to post
Share on other sites

When both threads try to access a queue protected by a shared mutex, they will access it one after the other, in a serial manner. And yes, when one thread acquires the mutex, the other threads will be blocked until they can grab it too.

If your goal is to protect the shared resource (queue in this case), having two mutexes would mean that two threads can access the resource simultaneously. If that's what you want, then cool. But if you want to make the queue thread-safe, sharing a single mutex is the way to go.

Edited by DiharaW

Share this post


Link to post
Share on other sites
40 minutes ago, DiharaW said:

If your goal is to protect the shared resource (queue in this case), having two mutexes would mean that two threads can access the resource simultaneously.

Don't use multiple mutexes to limit the number of simultaneous accessors - use a semaphore.

If you use multiple mutexes, how do you pick which one to wait on?  Then suddenly you have to synchronize that selection process as well or you're in for a world of hurt.

Edited by Nypyren

Share this post


Link to post
Share on other sites
1 hour ago, Nypyren said:

Don't use multiple mutexes to limit the number of simultaneous accessors - use a semaphore.

If you use multiple mutexes, how do you pick which one to wait on?  Then suddenly you have to synchronize that selection process as well or you're in for a world of hurt.

Yeah, i was trying to say that having multiple mutexes is a bad idea. Guess i didn't convey my idea properly. :D  How would a semaphore work to limit the number of simultaneous accessors? I'm curious cause i've only used it for signalling events (i.e kicking off a GPU submit job etc).

Share this post


Link to post
Share on other sites

Controlling simultaneous accesses is exactly what semaphores are meant for - see Wikipedia for example on how to think of their functionality.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!