WEBVTT 00:00.450 --> 00:00.980 Hi. 00:01.110 --> 00:04.910 We're back with the fifth video of this section Mew Texas. 00:04.920 --> 00:08.240 In the previous video we learned how to use callbacks and go. 00:08.360 --> 00:13.770 In this video will develop a small concurrent counter this counter will add one to an integer field 00:13.770 --> 00:14.990 in a counter type. 00:15.000 --> 00:17.710 This should be done in a concurrent safe way. 00:17.760 --> 00:22.410 If you're working with concurrent applications you have to deal with more than one resource potentially 00:22.410 --> 00:24.950 accessing some memory location. 00:24.960 --> 00:27.790 This is usually called race condition. 00:27.900 --> 00:33.000 In simpler terms a race condition is similar to that moment where two people tried to get the last piece 00:33.000 --> 00:39.050 of pizza exactly the same time their hands clock replaced a pizza with a variable and their hands with 00:39.050 --> 00:43.210 go routines and we'll have a perfect analogy. 00:43.230 --> 00:46.030 There is one character at a dinner table to solve this issue. 00:46.080 --> 00:51.960 A father or mother they've kept the pizza on a different table and we have to ask permission to stand 00:51.960 --> 00:54.620 up before getting our slice of pizza. 00:54.660 --> 00:59.670 It doesn't matter if all the kids ask at the same time they will only allow one kid to stand. 00:59.670 --> 01:01.950 Well a new text is like our parents. 01:02.010 --> 01:04.020 They'll control who can access the pizza. 01:04.020 --> 01:09.680 I mean a variable and they won't allow anyone else to access it to use a new text. 01:09.680 --> 01:12.680 We have to act to be Lochhead if it's already locked. 01:12.690 --> 01:15.920 Another guy routine is using it would have to wait until it's unlocked again. 01:17.050 --> 01:22.120 Once we get access to the new text we can lock it again do whatever modifications are needed and unlock 01:22.120 --> 01:31.330 it again we'll look at this using example of a concurrent counter me text is all widely used in concurrent 01:31.330 --> 01:32.500 programming. 01:32.500 --> 01:36.940 Maybe not so much in go because it has a much more idiomatic way of concurrent programming and its use 01:36.940 --> 01:42.100 of channels but it's worth seeing how they work for the situations where Channel simply don't fit so 01:42.100 --> 01:43.330 well. 01:43.330 --> 01:47.250 Let me show you how we define our counter structure. 01:47.350 --> 01:55.790 I've already created the may not go far where we'll write the code let us have the code here the counter 01:55.790 --> 02:00.640 structure has a field of int type that stores the current value of the account. 02:00.800 --> 02:06.710 It also embeds the new takes type from the sync package embedding this field will allow us to lock and 02:06.710 --> 02:11.150 unlock the entire structure without actively calling a specific field. 02:11.240 --> 02:17.540 Our main function will launch 10 go routines that try to add one to the field value of Count structure. 02:17.810 --> 02:19.930 All of this is done concurrently. 02:20.300 --> 02:26.960 So next we add the main function so we need to import sync and time packages which we're using in the 02:26.960 --> 02:29.190 main function okay. 02:29.200 --> 02:35.800 Let's say the file we've created a type called counter using a for loop. 02:35.820 --> 02:40.840 We've launched a total of 10 go routines as we saw in the anonymous functions launched as new guy routine 02:40.840 --> 02:46.200 section but inside every go routine we're locking the counter so that no more go routines can access 02:46.200 --> 02:46.760 it. 02:46.860 --> 02:50.120 Adding 1 to the field value and unlocking against others can access it. 02:51.030 --> 02:54.770 Finally will print the value held by the counter. 02:54.920 --> 02:58.370 It must be 10 because we've launched 10 go routines. 02:58.370 --> 03:01.410 But how can we know that this program is thread safe. 03:01.460 --> 03:08.270 Well go comes with a very handy built in feature called the race detector so let's look into presenting 03:08.270 --> 03:11.120 the race detector. 03:11.160 --> 03:13.440 We already know what a race condition is. 03:13.440 --> 03:18.720 To recap it's used when two processes tried to access the same resource at the same time with one or 03:18.720 --> 03:20.220 more writing operations. 03:20.220 --> 03:26.070 That is both processes writing or one process writing while another reads involved at that precise moment 03:27.280 --> 03:32.170 go has a very handy tool to help diagnose race conditions that you can run in your tests or your main 03:32.170 --> 03:38.840 application directly so let's reuse the example we just wrote for the new Texas section and run it with 03:38.840 --> 03:40.860 the race detector. 03:40.860 --> 03:45.680 This is as simple as adding the hyphen race command line flag to the command execution of our program 03:46.990 --> 03:51.760 let's save the file and move on to the command line terminal and execute the command. 03:51.760 --> 03:55.560 Go run hyphen race main dot go. 03:55.930 --> 04:01.450 Well not very impressive is it but in fact it's telling us that he has not detected a potential race 04:01.450 --> 04:07.590 condition in the code of the program let's make the detector of Hyphen race flag warnings of a possible 04:07.590 --> 04:12.000 race condition by not locking counter before we modified. 04:12.040 --> 04:17.690 Let's go back to the code file and make the changes we just need to modify the counter dot lock and 04:17.690 --> 04:24.240 counter dot unlock as comments in our code now inside the for loop comment. 04:24.250 --> 04:29.020 The lock and unlock calls before and after adding one to the field value. 04:29.020 --> 04:31.720 This will introduce a race condition. 04:31.720 --> 04:37.450 Let's run the same program again with the race flag activated save the file again and navigate to the 04:37.450 --> 04:44.680 terminal let's execute the previous command again I've reduced the output a bit to see things more clearly 04:45.280 --> 04:51.570 we can see a big uppercase message reading warning data race but this output is very easy to reason 04:51.570 --> 04:52.310 with. 04:52.560 --> 04:58.410 First it's telling us that some memory position represented by line 18 in our main dot go file is reading 04:58.410 --> 05:04.040 some variable but there is also a right operation in line 18 of the same file. 05:04.050 --> 05:09.810 This is because a plus plus operation requires a read of the current value and a right to add one to 05:09.810 --> 05:10.900 it. 05:10.950 --> 05:16.680 That's why the race condition is in the same line because every time it's executed it reads and writes 05:16.680 --> 05:23.080 the field in the count structure but let's keep in mind that the race detective works at runtime it 05:23.080 --> 05:27.240 doesn't analyze our code statically what does it mean. 05:27.310 --> 05:32.620 It means that we can have a potential race condition in our design that the race detector will not detect. 05:32.620 --> 05:34.180 Let's take an example of this. 05:34.240 --> 05:39.690 Get back to the code file and replace the code. 05:39.730 --> 05:42.280 Let me give the proper indentations. 05:42.520 --> 05:48.920 Fine we will take all locks and unlocks from the code and launch a single guy routine to update the 05:48.920 --> 05:50.120 value field. 05:50.510 --> 05:56.790 Save the file and go to the terminal when we run the previous command again we have no warnings. 05:56.800 --> 05:58.530 So the code is correct. 05:58.570 --> 06:05.190 Well we know by design it's not we can raise the number of Go routines execute it to and see what happens. 06:05.320 --> 06:12.640 Go back to the code file include the time package and make the changes to the for loop change. 06:12.680 --> 06:15.690 I less than 1 2 I less than 2. 06:15.740 --> 06:20.420 Also we need to add a small piece of code with the time dot sleep method along with the lock and unlock 06:20.420 --> 06:27.320 calls now say the file and let's execute the program again now. 06:27.560 --> 06:29.540 Yes the race condition is detected. 06:29.840 --> 06:33.770 But what if we reduce the number of processes in use to just 1. 06:33.830 --> 06:35.930 Will we have a race condition too. 06:36.080 --> 06:40.160 Let's try this execute the command. 06:40.280 --> 06:42.770 Go Max proxy equals one. 06:42.770 --> 06:46.950 Go run hyphen race main dot go. 06:47.030 --> 06:50.100 It seems that the race condition has been detected. 06:50.390 --> 06:55.450 This is because these scheduler executed one go routine first and then the other. 06:55.460 --> 06:59.820 So finally the race condition occurs with a higher number of Go routines. 06:59.830 --> 07:04.220 It will also warn us about race condition even if only using one core. 07:04.240 --> 07:09.220 So the race detector can help us to detect race conditions that are happening in our code but it won't 07:09.220 --> 07:13.030 protect us from bad design that is not immediately executing race conditions. 07:13.500 --> 07:19.740 A very useful feature that can save us from lots of headaches wonderful in this video. 07:19.740 --> 07:23.140 We've seen how to work with new taxes in the next video. 07:23.220 --> 07:24.240 We'll have a look at channels.