C++ Multi Threading Part 2: Mutex And Conditional Variables

  Рет қаралды 24,174

arisaif

arisaif

Күн бұрын

Пікірлер: 81
@user-rd3pl3on8c
@user-rd3pl3on8c Жыл бұрын
I've been reading a TON of substack posts on these subjects and I found myself simply getting MORE confused... you really do a great job getting to the point in a clear and illustrative way!
@tiantianliu5958
@tiantianliu5958 8 ай бұрын
Thank you Arisaif. It is clear and help me to eliminate some confusion.
@shuaili5656
@shuaili5656 Жыл бұрын
holy crap, I finally understand the condition variable stuffs, thank un soo much !
@Kazner0h
@Kazner0h Жыл бұрын
I was having such a hard time understanding this, but your effective and comprehensive breakdown got through to me.
@Hugo_Musk
@Hugo_Musk 10 ай бұрын
I love you man! You save my life and school's project!! Thanks a lot!
@gregwoolley
@gregwoolley 10 ай бұрын
I agree with the other commenters. You explain this really well. Your explanation is by far the most natural, simplest yet most comprehensive and detailed explanation I've come across. Big thank you. Please keep up your good work.
@teetanrobotics5363
@teetanrobotics5363 4 жыл бұрын
Hands Down. One of the best professors on the planet.
@muhammadalialam2846
@muhammadalialam2846 8 ай бұрын
Amazing video, very informative, explained everything in clearly. Thank you for this video :)
@moinmemon5764
@moinmemon5764 3 жыл бұрын
Best video to understand memory model, thread synchronisation. So impressed. Everything is crystal clear n organised. Keep up the good work man ✌🏻
@kristijanceple6026
@kristijanceple6026 3 жыл бұрын
This is truly genius and so good! I'm really glad for discovering this channel
@alexstephens9475
@alexstephens9475 2 жыл бұрын
Top tier explanation. I love that you explained many relevant things along with the concepts mentioned in the title, making a comprehensive learning experience instead of a fragmented one. Subscribed! :)
@wolverine9632
@wolverine9632 3 жыл бұрын
As soon as I saw the intro, I knew this was going to be some high quality content. AND YOU DIDN'T DISAPPOINT! Thank you very much, sir, from a new subscriber!
@kanhaglobal
@kanhaglobal 3 жыл бұрын
You put lots of work and time to explain this kind of hard topics with clear Presentations and Code ... Its make a huge difference in the Understanding of MT. GREAT WORK !!! Thanks A LOT.
@TheJank7
@TheJank7 2 жыл бұрын
Such a good video, the least I can do is to leave a comment and give a thumbs up. How did some many people not leave a like?
@minzhou1895
@minzhou1895 3 жыл бұрын
such a clear video. Looking forward to the other ones!
@arisaif
@arisaif 3 жыл бұрын
Happy to help :) Please consider subscribing to my channel.
@seanngpack4987
@seanngpack4987 4 жыл бұрын
awesome video! Very clear explanations, and visuals, feels like a solid college lecture
@cheggmi3637
@cheggmi3637 2 жыл бұрын
Your gift is teaching. You make a complex topics so simple. Thank you for all your videos, they have changed my understanding of C++. I will appreciate it if you can come up with a C++ training video with practical examples and projects, obviously not for free 😂. That, Sir, will be wonderful.
@emadpres
@emadpres 2 жыл бұрын
Another underated awesome video!
@anujabellad1634
@anujabellad1634 2 жыл бұрын
Superb! You explain it very neatly and nicely.
@pythagorasaurusrex9853
@pythagorasaurusrex9853 2 жыл бұрын
This tutorial is much appreciated! I enjoyed it and learned a lot about multi-threading stuff.
@arisaif
@arisaif 2 жыл бұрын
Glad you found it helpful!
@abeledea620
@abeledea620 Жыл бұрын
Thanks a lot for the info man,life savior video
@uchechinwasike1783
@uchechinwasike1783 2 жыл бұрын
This makes it so clear. Thank you!
@juliusmazer6485
@juliusmazer6485 4 жыл бұрын
Great video. Topics are both explained and presented very well. I wish you were my professor in college. Looking forward to everything multi threading!
@mitgharrib
@mitgharrib 4 жыл бұрын
Excellent video. Thanks. I am looking forward for your videos on Atomics (memory models) hopefully soon.
@arisaif
@arisaif 4 жыл бұрын
Thanks mitgharrib, glad you liked it!
@mrsinho1116
@mrsinho1116 3 жыл бұрын
Very clear, thank you a lot
@swarnendurc
@swarnendurc 3 жыл бұрын
Excellent explanation. 🙏👌🏾
@arisaif
@arisaif 3 жыл бұрын
Glad it was helpful! Please subscribe to my channel to get informed when the new content is available!
@user-tz5bz4cz9q
@user-tz5bz4cz9q 2 жыл бұрын
Thanks! Cool video lesson!
@rajatmittal4673
@rajatmittal4673 2 жыл бұрын
Awesome content well explained.
@jingtaoren1493
@jingtaoren1493 2 жыл бұрын
Wonderful job!!! Thanks~
@bilvadala
@bilvadala 2 жыл бұрын
One of the no nonsense and to the point video series I have ever got to watch and learn. Thank you so much, for your efforts. I have one suggestion on wider applicability of the language and taking advantage of object oriented programming through Design patterns. Would it be possible to start a new video series purely on Design patterns?
@arisaif
@arisaif 2 жыл бұрын
Great idea! Thanks for the suggestion.
@87yassmin
@87yassmin 2 жыл бұрын
Very clear Thanks 👌
@almosteasy9590
@almosteasy9590 2 жыл бұрын
Awesome video bro.. Keep it up 👆
@MrNyamchom
@MrNyamchom 3 жыл бұрын
Very well done !
@idoneoscom
@idoneoscom 3 жыл бұрын
Excelent!! thankyou Ari!
@angho8652
@angho8652 3 жыл бұрын
Thank you, very useful
@praveenbs8146
@praveenbs8146 3 жыл бұрын
Amazing video.
@armaghanasghar2911
@armaghanasghar2911 Жыл бұрын
Really good!
@amortalbeing
@amortalbeing 3 жыл бұрын
Loved it Thanks a lot
@maddieb9087
@maddieb9087 4 жыл бұрын
Fight on ✌️
@bioaktywny
@bioaktywny 10 ай бұрын
Dear Ari, I learned a lot watching your videos. I like your way of explaining issues. I wonder whether you're going to record those videos on other multithreading issues, including Thread Pool, threading safety in STL and those Abstract Multithreading ideas. It would be really helpful to me and I guess also many of your subscribers (including me - your subscriber :-)
@kevdaag2523
@kevdaag2523 3 жыл бұрын
At 31:25, in your example the notify_one() from the consumer to the producer is not necessary. The producer thread will reach the top of its loop and try to aqcuire the lock again, where it will be block until the consumer unlocks.
@MaxRob27
@MaxRob27 6 ай бұрын
notify_one() from the consumer (and so wait() in producer) is useful because of the possibility of the producer to produce 2 data while the consumer is consuming the first. If there weren't these two because consumer can consume data without possesing the lock (so it can consume while the producer produce another data) the producer could start another cycle of the while loop thus producing another data and overwrite the previous one that the consumer could never touch. It's been 3 years but i answered anyway.
@MaxRob27
@MaxRob27 6 ай бұрын
For the purpose i wrote a code that basically implement the consumer-producer logic shown in the video and this is an output with your changes: Main thread started Producer thread started Data produced: 290 Data produced: 575 Data produced: 957 Data produced: 361 Data produced: 924 Data produced: 393 Data produced: 648 Data produced: 169 Data produced: 347 Data produced: 716 Data produced: 8 Data produced: 540 Data produced: 839 Data produced: 109 Data produced: 3 Data produced: 701 Data produced: 643 Data produced: 176 Data produced: 431 Data produced: 864 Data produced: 640 Data produced: 780 Data produced: 733 Data produced: 170 Data produced: 193 Data produced: 102 Data produced: 856 Data produced: 242 Data produced: 129 Data produced: 868 Data produced: 519 Data produced: 388 Data produced: 361 Data produced: 204 Data produced: 944 Data produced: 692 Data produced: 747 Data produced: 915 Data produced: 133 Data produced: 7 Data produced: 572 Data produced: 986 Data produced: 695 Data produced: 347 Data produced: 220 Consumer thread started Data consumed: 220 Data produced: 127 Data produced: 829 Data produced: 500 Data produced: 990 Data produced: 749 Data produced: 694 Data produced: 259 Data produced: 598 Data produced: 100 Data produced: 659 Data produced: 399 Data produced: 483 Data produced: 462 Data produced: 353 Data produced: 910 Data produced: 498 Data produced: 860 Data produced: 759 Data produced: 988 Data produced: 626 Data produced: 930 Data produced: 406 Data produced: 589 Data produced: 946 Data produced: 442 Data produced: 879 Data produced: 710 Data produced: 646 Data produced: 451 Data produced: 41 Data produced: 454 Data produced: 693 Data produced: 259 Data produced: 29 Data produced: 990 Data produced: 712 Data produced: 666 Data produced: 145 Data produced: 319 Data produced: 796 Data produced: 162 Data produced: 381 Data produced: 19 Data produced: 420 Data produced: 405 Data produced: 393 Data produced: 335 Data produced: 855 Data produced: 62 Data produced: 785 Data produced: 169 Data produced: 344 Data produced: 9 Data produced: 370 Data produced: 840 Data produced: 900 Data produced: 790 Data produced: 766 Data produced: 164 Data produced: 645 Producer thread terminated Data consumed: 645 Consumer thread terminated Main thread terminated While this is an output with the producer waiting for the consumer notification: Main thread started Consumer thread started Producer thread started Data produced: 964 Data consumed: 964 Data produced: 597 Data consumed: 597 Data produced: 186 Data consumed: 186 Data produced: 296 Data consumed: 296 Data produced: 620 Data consumed: 620 Data produced: 209 Data consumed: 209 Data produced: 93 Data consumed: 93 Data produced: 228 Data consumed: 228 Data produced: 510 Data consumed: 510 Data produced: 2 Data consumed: 2 Data produced: 709 Data consumed: 709 Data produced: 185 Data consumed: 185 Data produced: 459 Data consumed: 459 Data produced: 452 Data consumed: 452 Data produced: 331 Data consumed: 331 Data produced: 606 Data consumed: 606 Data produced: 680 Data consumed: 680 Data produced: 600 Data consumed: 600 Consumer thread terminated Producer thread terminated Main thread terminated Pretty clear why it's useful now. As you can see way less data are produced in second case (the original) but every data is consumed at least (In each case the program is run for 1 ms).
@umakantasenapati726
@umakantasenapati726 3 жыл бұрын
Hi Arisaif....Excellent video on multi threading synchronization techniques ...Please come up with video on theadsfae STL ,CSP and Map Reduce...... Also i have watched your video on Atomic variables and memory model...It is very easy and clear to understand such a complex topic.....Keep making these type of videos....
@danmarian3606
@danmarian3606 3 жыл бұрын
perfect done
@momomadi2
@momomadi2 Жыл бұрын
thanks bro
@rbaccount4878
@rbaccount4878 3 жыл бұрын
Fantastic stuff! I really appreciate your efforts and time to educate others in a very clear way with the visuals. Hats off :) I have a question. At 31:46, in consumer(), why "ul.lock()" is needed after ConsumerData(data) ? Since its end of the while loop iteration, ul will be out of scope anyways and new ul.lock will happen at the start of the while loop.
@sangamchoudhary6977
@sangamchoudhary6977 Жыл бұрын
I have the same doubt, like what is the need of locking again, when it will reach to top after while loop it will get locked automatically by the unique_lock, so why there is need of manual locking
@MaxRob27
@MaxRob27 6 ай бұрын
@@sangamchoudhary6977 Becouse of the destructor of unique_lock. if the object ul goes out of scope the destructor call g_mutex.unlock(), and if it does it while g_mutex is already unlocked it will cause an error, so before end of {} lock is required to avoid the error
@frostfire2884
@frostfire2884 Жыл бұрын
Hero
@TheJank7
@TheJank7 2 жыл бұрын
Those emojis are so funny, good humor :)
@lopyus
@lopyus 2 жыл бұрын
Very clear video. Thanks for publishing this! Can you give the slides too?
@bharathkothandaraman5958
@bharathkothandaraman5958 Жыл бұрын
great
@autonomy_
@autonomy_ 4 жыл бұрын
Great video, one question though. Why does the ready variable exist for conditional variables? Seems odd that you would notify with ready set to false.
@arisaif
@arisaif 4 жыл бұрын
Because of spurious wake ups. If wait doesn't have a predicate (i.e. checking for ready), the thread might wake up without the producer actually sending a notification. From Wikipedia: "To allow for implementation flexibility in dealing with error conditions and races inside the operating system, condition variables may also be allowed to return from a wait even if not signaled, though it's not clear how many implementations actually do that."......... "Because spurious wakeups can happen whenever there's a race and possibly even in the absence of a race or a signal, when a thread wakes on a condition variable, it should always check that the condition it sought is satisfied. If it's not, it should go back to sleeping on the condition variable, waiting for another opportunity." en.wikipedia.org/wiki/Spurious_wakeup Also see this: stackoverflow.com/questions/8594591/why-does-pthread-cond-wait-have-spurious-wakeups
@mdirshadalam2617
@mdirshadalam2617 3 жыл бұрын
Hi Saif, Thanks for the video, it helps lot me. I made a thread to sleep for ten minutes using sleep_for. When other thread(s) comes , I need to wakeup , do the task and again sleep. Please help me for the issue. Thanks Irshad
@kilianklankers4418
@kilianklankers4418 2 жыл бұрын
Thank you for this awesome video! Keep Working :-) I got a question. At 32:26 you explain, that the sender lock on a shared mutex, and the reader lock on a unique mutex. At 18:46 you explain, that on the shared lock with shared mutex, multiple readers can be there, with no writer holding the lock. So I thought, that at 32:26, the sender must hold a unique lock, and the reciever can be a shared lock ( just reading data). Maybe you can help me to understand the my understanding problem?
@haiangho8210
@haiangho8210 3 жыл бұрын
Thank you arsaif, I have a question In the condition variable section. I wonder why do we have to put g_cv.notify_one() into ul.clock() and ul.unlock()? What if we remove ul.clock() and ul.unclock() what will happend? I tried on my PC and it still works if I remove. Is there any risk?
@arisaif
@arisaif 3 жыл бұрын
I think you mean ul.lock(). There is some explanation at 32:29. Quoting from en.cppreference.com/w/cpp/thread/condition_variable/notify_one: "The notifying thread does not need to hold the lock on the same mutex as the one held by the waiting thread(s); in fact doing so is a pessimization, since the notified thread would immediately block again, waiting for the notifying thread to release the lock." In general, it is better to only keep only whatever is needed in the critical section. If you don't have to put something int he critical section (in this case notify_one), it is better to take it out.
@rbaccount4878
@rbaccount4878 3 жыл бұрын
@@arisaif Thanks for the link and explanation. From your quoted text, I did not understand the part ".... since the notified thread would immediately block again, waiting for the notifying thread to release the lock". Please can you explain in detail. Thanks in advance.
@eigenfield
@eigenfield Жыл бұрын
Thank you. I have one question: Is mutual exclusion preserved during a "spurious wake-up"? To re-phrase it in another way, does the Consumer owns the mutex during a spurious wake-up?
@alessioinfantino5793
@alessioinfantino5793 2 жыл бұрын
I didn't understand the concept of predicate! More in particular, talking about the code, where is the predicate placed?
@arisaif
@arisaif 2 жыл бұрын
It is placed on the wait on the conditional variable. The OS sometimes wakes threads up spuriously. Checking the predicate ensures that we pass the wait only when the notification has arrived.
@thestarinthesky_
@thestarinthesky_ Жыл бұрын
Thanks for this great tutorial! I got a question here: @19:03 if we have multiple threads trying to read a shared resource but there is no modification, would we still need to have the critical section mutext locked? I mean race condition happens when at least one thread is trying to modify (write) into the shared resource. When there is no modification, what is the point of having mutex anyway as it will come at the price of performance, right?
@arisaif
@arisaif Жыл бұрын
You are correct, if there is no writer at all, no need for a critical section. However, notice that at 19:03, when I mention there is no writer, I mean that when there is no writer **at that moment** in the critical section. In that case multiple readers can be in the critical section. Later on, a writer might decide to write and get into the critical section. Once this happens, no reader can be there and the writer can write. In other words, the critical section provides mutual exclusivity between a set of readers and a single writer.
@thestarinthesky_
@thestarinthesky_ Жыл бұрын
​@@arisaif Thanks for the clarification. Please post more videos on C++ multithreading.
@avivran1198
@avivran1198 2 жыл бұрын
Hi, on time 29:40.... I don;t understand the following 2 (C++ code) lines // if blocked, ul.unlock() is automatically called. // if unblocked, ul.lock() is automatically called. If mutex is taken at the time of call, the caller is blocked... so what do you mean by "if blocked, ul.unlock() is automatically called" how come "ul.unlock() is automatically called"?? Thanks for the very good series. Appreciated!!
@arisaif
@arisaif 2 жыл бұрын
// if blocked, ul.unlock() is automatically called: This means if the condition is not met (i.e., we have to block and wait), then ul.unlock() is automatically called so that other threads can progress and hopefully set the condition at some point so that we get unblocked. // if unblocked, ul.lock() is automatically called: This means if the condition is met and we can progress, then ul.lock() is automatically called so that other threads cannot get into the critical section. Hope this helps. If you find my channel helpful, please consider subscribing.Thanks!
@kreaturen
@kreaturen 2 жыл бұрын
I'm just wondering, at 14:45, the result appears almost instantaneously, but on my computer it takes quite some time actually... Did you skip it or is it supposed to run really quick?
@arisaif
@arisaif 2 жыл бұрын
It doesn't take a long time on my system. Make sure you are compiling with -O3 and also in release mode. You could reduce the number of threads and the number of times we loop. See this example: godbolt.org/z/o7o6frP7x
@kreaturen
@kreaturen 2 жыл бұрын
@@arisaif Thanks. I'm using Visual Studio atm (using a school licence), and unable to find reference to this -o3 thing, so I'm not exactly sure what that is or where to put it. It's not a big deal though, doesn't matter a bit slow. It's just for practice and your tutorials help a lot. Threads and shared resources proved a bit tricky to get right on my own, but this is on point 😅👍
@moviewatch12
@moviewatch12 4 ай бұрын
How to wake up a specific thread?
@ThePaypay88
@ThePaypay88 3 жыл бұрын
great english
@skilz8098
@skilz8098 3 жыл бұрын
This in regards to the section of code that runs the Incrementer 1,000 times without locking the shared resources. I fully understand the concept of race conditions and how this code can generate undefined behavior. However, on my system (architecture, platform, and compiler) I can not reproduce these race conditions. I have an Intel Core 2 Quad Extreme running Windows 7 Ultimate x64 and I'm using Visual Studio 2017 with C++17 enabled. I've run this short program a dozen times, and every time I have run it, every printed value is 10,000. As I said, it should be undefined behavior, but I can't reproduce it. I don't know if this pertains to either Intel's CPU (ISA and instruction sets), the C++ compiler that I'm using, or Windows 7 task scheduler for multiple threads... However, I can take away quite a bit from this video when it comes to designing safe and reliable multithreading applications. Very good video with simple explanations and examples. Keep up the great work!!!
@arisaif
@arisaif 3 жыл бұрын
I haven't tested on a system with specifications like yours, but I suspect it just happens to give you the right answer on your machine, but this won't be guaranteed if you move your code to another machine. I suggest you also try it on a different machine or perhaps an online compiler like this: www.onlinegdb.com/online_c++_compiler
@amortalbeing
@amortalbeing 3 жыл бұрын
By the way what's the answer to your homework>?
C++ Multi Threading Part 3: Atomic Variables and Memory Models
1:03:04
World’s Largest Jello Pool
01:00
Mark Rober
Рет қаралды 104 МЛН
A little girl was shy at her first ballet lesson #shorts
00:35
Fabiosa Animated
Рет қаралды 16 МЛН
What it feels like cleaning up after a toddler.
00:40
Daniel LaBelle
Рет қаралды 88 МЛН
Задержи дыхание дольше всех!
00:42
Аришнев
Рет қаралды 3,7 МЛН
Learn C++ Multi Threading in 20 Minutes
21:04
arisaif
Рет қаралды 67 М.
Water powered timers hidden in public restrooms
13:12
Steve Mould
Рет қаралды 742 М.
What is Mutex in C++ (Multithreading for Beginners)
12:29
CodeBeauty
Рет қаралды 41 М.
Thread Synchronization Primitives - Learn Modern C++
29:47
Code Blacksmith
Рет қаралды 12 М.
E02: Stupid C++ Tricks: Most Dangerous C Functions (E02)
23:33
Dave's Garage
Рет қаралды 181 М.
Why Isn't Functional Programming the Norm? - Richard Feldman
46:09
World’s Largest Jello Pool
01:00
Mark Rober
Рет қаралды 104 МЛН