C++ Tutorial 16 : C++ Threads

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
well hello internet and welcome to part 16 of my c-plus video tutorial in this part of the tutorial we're gonna talk about threads time protecting shared resources and then we will create some examples and the differences between calculating primes with and without threads like always all the code is available in the description underneath the video and if you haven't watched any of the previous parts you most definitely should otherwise you will be confused and I have a lot to do so let's get into it alright so here we are again and you can see here a list of all of the potential libraries we may or may not use in this tutorial so make sure you have all those and everything will be safe the very first thing I want to do here is I want to create a function that it's going to generate a random value based off of a maximum value that is passed to it we're gonna use this in a couple examples so I'm just gonna come in here and go SRAM's and we're gonna use time once again the in milliseconds to generate a sort of random value and then we will return set value by going rands and then modulus on whatever the max is and of course the way modulus works is it's impossible to get a value that is bigger than whatever this max is whenever we use it like this all right so I'm gonna first off I'm going to show you a little bit about threads and we're gonna ramp it up until we get more and more complicated and then I'm also gonna show you some neat things we can do time with time inside of c++ so this is going to be called execute thread and it is going to be passed an ID just to represent the different threads we're gonna create now if I want to get the current time let's just call it now time all I need to do is go standard and chrono and system and then underscore clock and then now and that is going to give me the current time in milliseconds all right so now that I have that what I need to do is convert to a time that we can output so I'm gonna go time underscore T and I'm gonna call this sleep time and then let's go down to the next line and we can once again go chrono system underscore clock and then two time underscore T and then we're gonna pass now time into that guy right there then we need to convert to our current time zone because it's not gonna make sense otherwise so I'm gonna call this my local time and then we go and put a star inside of there and local time and then we pass sleep time inside of there so we're gonna be using this to make our threads go to sleep for certain periods of time okay so useful stuff now what I'd like to do is print some information out on our screen so we'll go thread and then we'll print out whatever ID we assign to that thread and then we will assign a sleep time suppose space inside of there so sleep time and then we can go and output the time that we put our thread to sleep just by passing our sleep time inside of there and then we'll throw in a new line of course all right now you're gonna be able to also get a lot of information about time in general inside of C++ and I went and created these ahead of time so you don't have to watch me type them you can see right here exactly how we can get our month or day our year our hours minutes and seconds just by using these little shortcuts that we have right there you're gonna bodge your screen of course at any time if I'm going a little bit too quick and now what I want to do is go and actually put our thread to sleep now I didn't explain this but basically a thread is just a block of code that executes now for example we've been using threads for forever mayne is a thread this is just the main thread it's a block of code that executes now whenever you are working with multiple threads that means that you are working with a multi-threaded application okay so it's quite simple and what's great about threads is that you will actually be able to utilize your processor to actually execute different blocks of code at the same time to sometimes get better calculations quicker and so forth and so on as you will see as this tutorial continues what I want to do right now is put my thread to sleep and that just means that it's going to stop executing for a certain period of time so to do that you just go this thread sleep and then for and then you go standard chrono seconds and then what I'm gonna do is I'm going to use our get random function to have it sleep up to three seconds so it's gonna be somewhere up to three seconds not more no less then what I'm gonna do is I'm gonna get mine out on and once again standard chrono system clock and now and reassign that again get my sleep time once again and I can just go and get this guy right here and copy it so I don't have to waste time typing and then I'm gonna grab this guy up here again and copy this so that we can see the difference in the time of the thread from the time that a woke and then fell back asleep now I'm gonna change this to a wake time and everything else can be exactly the same as it was okay we can save that and then I can come down here and create the thread inside of main and to do that we just go standard and thread and let's just call it th one and then if you want to actually call this function so execute thread and pass it an ID how you do that is you just come up here and you go execute thread which is the function that you want to execute and one is going to be the ID that I pass inside of it and then I can go and copy this and do it again for another thread and we can just change the ID to that two two and then on top of that what you need to do is join the thread to the main thread meaning that main waits for this thread to stop executing before continuing execution of code in main so we can go th one and join and then we're gonna do exactly the same thing for the other one so there we go and just change its th two of course and change this to th two also alright and we can go and save that and run it and you can see right there that there was absolutely no sleep time between these different parts let's run it again and there it is six seconds six seconds six seconds so they basically executed exactly the same time let's run it again and there you can see that it actually did take some time though and you can see right there that of the random number of seconds meaning that this thread was asleep for two seconds and this right here was asleep for just one second okay so just a brief overview of how you can create threads how you can get a lot of information timewise and then how you can put threads to sleep and then have them come back awake now what I want to do is show you how you could create a pool of threads and then have them access the same piece of information and what we're gonna do is sort of simulate a bank account I'm gonna need another function here and I'm gonna call this get time and it's just gonna make getting the current time a little bit easier so I'm gonna go Auto and there's a rule at point of typing that out again because I already did this once before so let's just paste that inside of there just to keep your tongue for you keep you from wasting your time all right so that's what it's gonna do it's gonna return our time to us just as I explained in the previous example and then I'm also going to have a global here and this is going to be our account balance for our fake checking account or whatever you want to call it then we are also going to use this mutex and what its gonna do is protect shared data from being accessed at the same time so it's going to protect the threads from accessing the account balance yeah exactly the same time and pulling it money out of it so we're going to call that account lock and you're gonna see how that works and then we're gonna actually create the function that is going to be accessing that account balance and we're going to get an ID as well as a withdrawal amount from the account and then the exception safe way for us to block or balance from being accessed by more than one thread at a time is to use this guy right here and I'm gonna go lock and account lock and basically it is going to restrict access to the entire scope of this function once one of the other threads comes in here and tries to execute this code you would also be able to come in and do a count lock and then lock specifically and then followed by a count lock and unlock and then wrap your code inside here so the code that you would want to be safe would be right inside of right between lock and unlock but that in some situations is not safe for if an exception would occur during your code execution sometimes you're gonna use it sometimes you will not okay so there's two different ways to lock down your code then I'm gonna come in I'm gonna go this thread and sleep just like we did before for in here I'm just gonna go standard chrono and seconds I could use get random but I'm just gonna change this to 3 seconds just so you can see the execution taking place on the right side of the screen and this is this thread and then let's print out some information about the actual money being withdrawn from our account so I'm gonna say whatever the idea is or the ID is for the person accessing this and I'll say withdrawal and the amount of money that they want to withdraw from the account which is gonna be the withdraw amount that they passed inside of here and then I can print out some information on exactly when they tried to pull that information or that money out of the accounts and I'll call get time to get that information and of course a new line then of course I'm gonna have to verify that we have any money in the accounts so I'll say account balance - with drawl is greater than or equal to 0 well in that situation I can say account balance and take the withdrawal amount out of it out of our account and then let's just print out some information on the new account balance so we'll say new account balance is and then for now whatever that is all right so we'll be able to sit here and actually watch the account balance go up and down based off of the different threads trying to access and retrieve money out of our account else if they're trying to withdraw money that is not available inside of our account we're just gonna print out a message it says not enough money in account and we don't need to print out whatever the amount is inside of there just keep it nice and simple Oh what the heck let's go and print it out so okay well I can just go like this and say current balance is and account balance and then print that out all right so we have that all set up now we can go down inside of main and actually execute this by creating some thread pools so what we're gonna do just good to understand that whenever we create these threads that they are going to access the account randomly so there's no definite way that they you know the first thread is gonna access the account then the second and so forth and so on so don't expect that so and actually create our thread pool and then let's load our threads that we create into our array that we have here our array of threads and then what they're all going to be doing which is accessing the function called get money and it's going to pass an ID and then they're all going to try to risk take out $15 out of our account all right so that created those threads and then we need to of course join them to our main function that we have here our main thread however you want to call it and to do that you just take this guy right here and follow that up with join and there you go and now we can execute it let's move this over and there we go whoops there was an error I forgot to put an equal sign inside of there no big deal save it run it and there you're gonna see execution taking place remember there's a three-second pause so two tries to withdraw $15 and there's all that information to account balance eighty-five one tries to withdraw $15 and you can see that they are going in there and accessing the account and they will continue accessing the account every three seconds until we reach a point in we have no more money in the account see not enough money any accounts and then they are no longer going to be able to access that account alright so there is how we can go and block our threads and create thread pools and have everything sort of simulate a real-world transaction and now I'm going to cover how we can calculate prime numbers with as well as with out threads first I'm going to cover how to calculate Prime's without threads and then we can see the performance differences so we can come in and I'm gonna call this find Prime's and we're going to be using unsigned int in this situation so we're gonna have a starting value and then we are going to have an ending value as well another unsigned int which is going to be the ends and then we can also have a vector where we are going to store this information inside of so vector this is also gonna be an unsigned int and vector so we'll be able to pass the vector inside of there to use it then what we're gonna do here is just cycle through numbers while ignoring even values because an even value of course cannot be a prime so I'm just gonna go unsigned and X is equal to whatever starting value they want me to start checking for and we're gonna continue checking as long as X is less than or equal to the end point the X here is going to just jump over any even values of course and then once again unsigned and yes I know there is neater ways to calculate Prime's I will cover those eventually I just wanted to keep this nice and simple so I'm just gonna cycle through all of these different values increment the value of Y I'm gonna say F and let's throw another one of those in there if modulus Y is equal to zero well we know in that situation that we do not have a prime value else if Y plus one is equal to X in that situation we have a prime value so we're gonna go push it onto our vector and there we go alright so just want to keep this nice and simple and that's how we are going to find out if a pro is prime or not and then we are going to push it on the vector or not push it onto the vector ok so we got that now I can go and create said vector that we've been talking about and again this is going to be an unsigned int and we can go prime caught prime vector I'm also going to check how long it takes for us to check these different values so I'm gonna go and get our time and then I'm going to say find Prime's and let's say I want to go from 1 to 100 thousand and then I'm going to of course pass in our vector that we want to add those values to then after I do that of course I can come in here and actually print out all of those values some prime vector once again so that we can see all of them print out on the screen and we can do a new line and then I'm going to also come in and get our end time and just by calling clock and then I can print out some information in regards to how long it took for us to find all the prime values in 100,000 so print that out call this execution time and to get the execution time we just go end time - start time but then we're gonna have to divide by clocks per tick and that's just the number of representations that a number of clock ticks pertinent it make up each second if we want to find out how many seconds have gone by so we just go clocks per second and then end this and clean the buffer alright so there we go and everything else is exactly the same and we can run this and test out how long it's gonna take to find all the primes in up to 100,000 and there you can go and then we can write down our time you can see all the primes flying through so that was two seconds and whatever so many milliseconds so we remember that I'll actually write that down so that's gonna be 2.12 and then we're gonna use threads and then we're gonna see which are faster so to use threads what am I gonna have to change well I don't I actually don't even need these guys so let's just get rid of that altogether well one thing I want to do of course I want to protect accessing our vector by more than one thread at a time someone need got another thing I'm gonna do just to keep this simple is I'm going to create a global vector here so unsigned int and have that be prime vector and there we go got that set up then I can just go and get rid of passing the vector inside of here so let's get rid of that I'm however going to try to keep everything roughly the same because if I go and change a whole bunch of different things then you know the amount of time that we're calculating isn't going to make that big of a difference or you know we're not gonna be able to properly compare two things to each other so for this guy right here everything is going to remain exactly the same I don't believe absolutely any of these different things are gonna change actually so that the the only thing that most definitely is gonna well this is going to be called prime of X so prime of X and there's that and then I am going to use lock and unlock in this situation so vector lock and lock and then we're gonna do the same thing for unlock and that's of course going to keep people from accessing the vector multiple threads accessing the vector at the same time okay so we got that all set up I'm then going to use another function I'm gonna kind of keep this what's going on inside of main here I'm just gonna put it right here so I'm gonna call this void find Prime's with thread threads and this is going to be passed an unsigned int if anything this is going to sort of maybe slow down the thread it's just talking in milliseconds but that's not gonna make big changes in our final results let's see what else we can put inside of here I'm gonna go on int and I need a way to create these actual threads so you know there's really no way around it and that is really going to be the differences between having one thread and having multiple threads because of course there is going to be some machine time that is going to have to be devoted to actually creating threads and in the other you know whenever you only have one thread of course you don't have to devote time to creating each of those threads there's a overhead to using threads so whenever you're working on very small numbers having multiple threads makes absolutely no sense but whenever you have very very very large numbers as you're gonna see it does actually impact the results even for a hundred thousand you're gonna see that there are indeed you know there is a difference between using threads and not using threads so what I'm going to do here is I'm gonna divide up the calculations so that each of the threads is going to operate on a different block of prime so I'm gonna call that thread spread and that's just gonna be equal to whatever the end is divided by the number of threads and then once again I'm side and new and we're going to change start plus whatever the thread spread is so I'm just let's say I'm only working with ten values and I create five threads to calculate that the first threads gonna handle one and two the next thread is gonna handle three and four the next one is five and six and I think you get it so that's what I'm doing here thread spread and that's gonna be minus one however and what else we gonna do well I need to create my Prime list for each of my threads so I'm gonna say for unsigned int X is gonna be equal to zero X less than and the number of threads and you can see there's definitely some overhead and working with threads creating threads of course and then I'm gonna call find crimes and then of course I'm gonna pass in whatever the start is as well as the ending from where we are executing and then after that I have to change our starting time so thread spread once again Anne's new end and increase the ending once again so thread spread all right and then we have that I'll set up and then I need to join all of our different threads together somebody go for and auto once again let's just call the thread t and that's gonna be thread vex and C join so we're creating a thread pool once again to operate on creating these calculations and then down inside of here I'm just gonna get rid of all this stuff because I already created a lot of it inside of this function right here and of course I need to monitor the amount of time that went and by otherwise it would be kind of worthless and then I can call find crimes with thread and I'm gonna start at one just like I did with the previous example then I'm going to go up to a hundred thousand and then I'm going to use what I discovered on my machine is the optimum number of threads which is gonna be three might be different on different computers I'm then going to come in and get our end time so that we can see the difference and then I can of course print out all of my threads just like we did previously so I by accessing our vector where we stored all of our threads and there goes that guy and then of course we don't want to forget we want to print out the amount of time that it took to execute our threads and then we can compare that between using one thread and multiple threads somebody go and time on a start time exactly like we did before and double oops double and clocks per second in ndele all right and we have returned inside of their find primes oh this is gonna be Prime's with threads right find Prime's with threads yep looks good as long as I didn't mess up everything should be fine so we can see right here our execution time is two point one two eight and we can run this and there it goes and here using multiple threads or using three threads to be exact we were able to pretty dramatically even with a very very small data set cut down our time by about one second little bit less than one second alright so there you go guys there are multiple different examples of different ways you can use threads you can go in here and look at the different results depending upon increasing or decreasing the number of threads we have inside of here I can just go and use one thread right now just change it to that and 1.46 is what we had previously and you can see there we used one thread and it took you know considerable amount more alright so hopefully you found this tutorial useful and elect always please leave your questions and comments below otherwise till next time
Info
Channel: Derek Banas
Views: 88,402
Rating: 4.7862201 out of 5
Keywords: C++ Threads
Id: IdwJdJw65tU
Channel Id: undefined
Length: 25min 22sec (1522 seconds)
Published: Tue May 15 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.