What is a mutex in C? (pthread_mutex) CodeVault https://www.youtube.com/watch?v=oq29KUy29iQ Transkript (automatisch erstellt) 0:00 so we left at this issue where we have a race condition for writing to the males variable if we launch this again of course we're going to get 0:08 a different number than 2 million which is what we would expect if we would just do everything in one thread 0:18 now we know why that is but in this video i'm going to talk about how to solve this issue an answer is using a 0:25 mutex this is how you can solve the issue a mutation is sort of a lock around a section of code so to speak so for example what we could do is let's 0:36 say have a variable called lock set it to zero and set it to one whenever you're doing something and set it to zero whenever 0:45 you're done doing something okay and before all this check if the lock is already one so if the lock is already 0:55 one right before you are trying to set a locked one then you should sort of wait until the lock is zero 1:08 this way uh what would happen is that if a thread tries to actually increment the males variable well it certainly 1:18 will increment it but it will also set the lock to one so if the second thread comes in at the same time and tries to increment 1:26 it it's gonna stop at that condition because the lock is gonna be set to one so only after we're done incrementing 1:34 it's gonna be reset to zero so then the second the second thread could come in and read increment and write in the right order 1:44 right so nowhere you would have a thread that just starts reading and then the other thread will start executing like we had in that example 1:55 i showed you the race condition right so in the race connection we had a read and then the thread got paused for whatever 2:04 reason and then the second that came in and started to read increment right like seven times 2:11 and then this guy had inside its memory said its cpus registers the old value right which was then written to the 2:19 memory like this we can prevent it but how do we wait until the lock is zero well we 2:26 don't really have to implement our own variable with log things and whatnot the pthread the posix thread api actually has something like that 2:35 implemented that we can already use and it's much safer than what we would do here so to start using it so we're gonna 2:44 remove this lock variable we're gonna replace it with a p thread underscore mutex underscore t and call it let's say mutex 2:52 for now for simplicity's sake okay so we have a mutex and well before we can use it we have to initialize it so 3:01 to initialize it we go down here and let's say we initialize it before creating the thread of course i'm going to say pthread mutex 3:10 init right and this guy takes in just two arguments the address to that mutex i'll just add mutex and then some attributes which we're not going to get 3:21 into right now so those those can be set to null and it's going to be all right so just set everything 3:28 basically when we pass here no it's going to set everything to default and that's all right for us and of course with an init comes with 3:36 it comes with a destroy so we're going to have to also destroy the memory that's been allocated here so i'm going to 3:42 call peter mutex destroy and this guy just takes in the address to the mutex no more second parameter right so pictured mutex 3:52 init with the mutex and then destroy and now we have the mutex available to us we haven't used it yet in any way shape or 3:59 form we just initialize it now let's go to actually using it so here these three operations so 4:08 checking if the lock well has been locked has been taken by someone some tread and waiting until that uh lock is unlocked 4:19 and also setting to one the lock once we're done doing all that is being accomplished with just one function and that function is called 4:29 pthread mutex block so lock all it takes is just a reference to our mutex 4:38 and that's it so this just this one function does all that for us so we don't have to care about waiting and not waiting and 4:46 finishing waiting for all that now in place of this operation setting our lock to zero basically 4:51 unlocking the mutex is just the call to pthread mutex unlock as you might have guessed and we just pass in the mutex and that 5:02 is it my friends all you have to do is just call lock and unlock and all of a sudden the result is going to be correct so now 5:11 if we try to launch this it's going to take a bit longer but we do get the right 5:19 result 2 million right 2 million even though we have incremented it a million times and it's in a multi-threaded context 5:27 it works and we can even increment it more times like let's say 10 million and it's still going to work it might take a bit longer 5:37 but it is still going to work there you go that is 20 yeah 20 million so what does this do 5:44 actually well this locking and unlocking of mutexes is basically protecting think about it as sort of 5:55 some brackets between a part of a code that you want to protect to protect against what protect against 6:04 other threads executing it at the same time so if at any point a thread is executing this 6:11 this line of code there's not gonna be any other thread that's gonna execute this same line of code simply because there's a mutex 6:19 around it if we didn't have the mutex we didn't have this we wouldn't have this um certainty and then 6:27 we could get into race conditions of course not all the time not all instructions have to be like that because 6:33 if all instructions are going to be executed only by one thread at one point in time might as well just have one single 6:41 thread executed yellow right now the idea is that we want in this case correct data and this program on its own doesn't do anything 6:50 useful so it's just a good example so that you understand what's going on behind the scenes and why mutexes are 6:59 needed and before anyone asks this actually works with more than just one thread so if i for example try to create two more threads let's 7:09 copy and paste this and i'm gonna initialize here p3 and p4 and this case going to be p b 4 p 7:18 3 okay and then i'm going to join it two more times so let's say p3 and p4 here and guess just for correctness 7:31 sake let's do it let's give it a different uh error number everywhere not really a big deal but just to be 7:41 safe and now if we try to execute with four four threads you'll notice that we are gonna get 7:51 a pretty long wait time but we're gonna get a result of 40 million without those threats that result 7:58 probably would have been in the 20 million let's actually check and see if i try to launch this without the 8:06 locks and unlocks as you can see it's one or it's 15 million so that was a pretty bad result if we didn't use stress but 8:15 notice it was faster so it is much better to use to do not use mutexes whenever possible but in this case we kind of have to 8:22 it's just an example you'll see in the future exactly when to when and why to use mutexes now one more thing that i forgot to 8:30 mention is that a race condition can only occur on a multi-core processor if you have a single core processor 8:39 then it's very unlikely that you will encounter a race condition but as nowadays most like 99 of the cpus out there are multi-core 8:49 even though low powered ones you are going to encounter this okay that's about it for today thank you so much for watching if you have any 8:58 questions leave them down comments below or on our discord server of course the source code of today's video will be also down in 9:06 the description below on our website thank you so much for watching and take care bye