WEBVTT 00:00.180 --> 00:06.750 Hey we're now at the last video of this section using it all concurrent Singleton in the previous video 00:06.750 --> 00:09.430 we dived into using channels in this video. 00:09.440 --> 00:11.860 We'll put all our knowledge in a single package. 00:11.910 --> 00:16.170 We'll create structure or variable that could only exist once in our code. 00:16.230 --> 00:21.960 All access to this structure should be done using the pattern described but we'll write this with concurrency 00:21.960 --> 00:22.810 in mind. 00:22.830 --> 00:27.210 We'll write a concurrent counter like the one we wrote in the new text is video but this time we'll 00:27.210 --> 00:28.950 solve it with channels. 00:28.950 --> 00:34.720 So let's start by writing the unit test to restrict concurrent access to the Singleton instance. 00:34.770 --> 00:39.010 Just one go routine we'll be able to access it will access it using channels. 00:39.090 --> 00:43.950 The first one to add the second one to get the current count and the third want to stop the go routine 00:44.430 --> 00:50.400 will add 1 10000 times using 10000 different go routines launched from 2 different Singleton instances. 00:50.490 --> 00:55.980 Then we'll introduce a loop to check the count of the singleton until it is 5000 but we'll write how 00:55.980 --> 00:58.500 much the account is before starting the loop. 00:58.770 --> 01:03.490 Once the count has reached 5000 the loop will exit and quit the running go routine. 01:03.540 --> 01:05.220 Now let us write the test code. 01:05.310 --> 01:11.220 I've already created 2 files Singleton Dok Go and Singleton underscored test Doc go within the folder 01:11.550 --> 01:18.660 channel underscore Singleton open the Singleton test Dok Go file here at these lines of code here what 01:18.660 --> 01:23.770 you see is the full test which will use after creating two instances that Singleton. 01:23.770 --> 01:29.220 We've created a for loop that launches the add one method 5000 times from each instance. 01:29.250 --> 01:33.230 This is not happening yet they're being scheduled and will be executed eventually. 01:33.260 --> 01:37.980 We are printing the count of the singleton instance to clearly see this eventuality depending on the 01:37.980 --> 01:42.940 computer it will print some number greater than or equal to zero and lower than ten thousand. 01:42.960 --> 01:47.070 The last step before stopping the go routine that is holding the count is to enter a loop that checks 01:47.070 --> 01:51.530 the value of the count and waits 10 milliseconds if the value is not the expected value that is ten 01:51.530 --> 01:52.250 thousand. 01:52.260 --> 01:57.360 Once it reaches its value the loop will exit and we can stop the Singleton instance will jump directly 01:57.360 --> 02:02.970 to the implementation as the requirement is quite simple move to Singleton Dok Go and start with the 02:02.970 --> 02:07.590 implementation first of all will create the go routine that will hold the count. 02:07.770 --> 02:08.550 Okay. 02:08.820 --> 02:14.040 We created three channels as we mentioned earlier the ADC each channel is used to communicate with the 02:14.040 --> 02:20.600 action of adding one to the count and receives a bool type just to single add one we don't need to send 02:20.600 --> 02:25.940 the number although we could be get count c h channel will return a channel that will receive the current 02:25.940 --> 02:26.980 value of the count. 02:27.050 --> 02:30.150 Take a moment to reason about the get count see a channel. 02:30.260 --> 02:33.360 It's a channel that receives a channel that receives into times. 02:33.530 --> 02:36.330 It sounds a bit complicated but it will make more sense when we finish. 02:36.330 --> 02:41.450 Example Don't worry the quit C channel will communicate to the go routine that it should end its infinite 02:41.450 --> 02:44.270 loop and finish itself to. 02:44.450 --> 02:47.640 Now we have the channels that we need to perform the actions we want. 02:47.660 --> 02:52.610 Next we launch the go routine passing the channels as arguments as you can see we're restricting the 02:52.610 --> 02:58.040 direction of the channels to provide more type safety inside this go routine we create an infinite for 02:58.040 --> 03:02.150 loop this loop won't stop until a break is executed within it. 03:02.150 --> 03:06.770 Finally the select statement if you remember was a way to receive data from different channels at the 03:06.770 --> 03:08.300 same time. 03:08.420 --> 03:14.160 We have three cases so we listen to the three incoming channels entered his arguments first one is the 03:14.160 --> 03:17.240 ADC case which will add one to the count. 03:17.310 --> 03:20.400 Remember that only one case can be executed on each iteration. 03:20.400 --> 03:25.980 So no go routine could be accessing the current count until we finish adding one next the get count 03:25.980 --> 03:28.860 see each channel receives a channel that received an integer. 03:28.860 --> 03:33.600 So we capture this new channel and send the current value through it to the other end. 03:33.720 --> 03:38.250 Then the quick CHF channel breaks the for loop so the go routine ends. 03:38.250 --> 03:38.910 One last thing. 03:38.910 --> 03:44.070 The init function in any package will get executed on program execution so we don't need to worry about 03:44.100 --> 03:46.830 executing this function specifically from our code. 03:46.860 --> 03:48.270 Now we'll create the type. 03:48.270 --> 03:53.980 The tests are expecting we'll see that all the magic and logic is hidden from the end user in this type. 03:54.240 --> 04:01.700 As we've seen in the code of the test let's add the type Singleton struct also lets out the package 04:01.700 --> 04:10.920 name find the Singleton type won't hold the account value we created a local value for it called instance 04:11.130 --> 04:15.450 and we return the pointer to this instance when we call the get instance method. 04:15.600 --> 04:19.860 It's not strictly necessary to do it this way but we don't need to allocate a new instance of the singleton 04:19.860 --> 04:26.280 type every time we want to access the accounts variable first the add one method will have to add one 04:26.280 --> 04:30.860 to the current count how by sending true to the ADC each channel. 04:30.990 --> 04:31.980 That's simple. 04:31.980 --> 04:38.260 So let's add the code for this this small snippet will trigger the ADC each case in our go routine in 04:38.260 --> 04:45.490 turn the ADC HK simply executes count plus plus and finishes letting select channel control flow that 04:45.490 --> 04:52.210 is executed on init function above to execute the next instruction so we add the next lines of code 04:52.210 --> 04:57.460 with this instruction he get count method creates a channel every time it's called and defers the action 04:57.460 --> 04:59.550 of closing it at the end of the function. 04:59.890 --> 05:05.800 This channel is on buffered as we've seen previously in this section and buffer channel blocks the execution 05:05.800 --> 05:08.080 until it receives some data. 05:08.080 --> 05:13.900 So we send this channel to get count C H which is a channel 2 and effectively expects a channel type 05:13.990 --> 05:19.420 to send the current count valley back through it to get count method will not return until the value 05:19.420 --> 05:21.910 of count variable arrives to the rez. 05:21.910 --> 05:27.130 C H channel he might be thinking why aren't we using the same channel in both directions to receive 05:27.130 --> 05:28.740 the value of the count. 05:28.750 --> 05:30.970 This way we will avoid an allocation. 05:30.970 --> 05:35.500 Well if we use the same channel inside the get count method we'll have two listeners in this channel 05:35.950 --> 05:40.600 one in select statement at the beginning of the file on the init function and one there. 05:40.990 --> 05:44.170 So it could resolve to any of them when sending the value back. 05:44.200 --> 05:46.770 Let's add some more lines of code to our file. 05:46.780 --> 05:52.240 Finally we have to stop the go routine at some moment the stop method sends the value to the Singleton 05:52.240 --> 05:57.340 type go routine so that the quit c h case is triggered and the for loop is broken. 05:57.400 --> 06:01.840 The next step is to close all channels so that no more data can be sent through them. 06:01.840 --> 06:06.610 This is very convenient when you know that you won't be using some of your channels anymore time to 06:06.610 --> 06:08.790 execute the tests and take a look. 06:09.190 --> 06:17.370 Save the file a move back to the terminal we need to save test fall to done now run the command go test 06:17.400 --> 06:24.680 hyphen v very little code output but everything has worked as expected in the test we printed the value 06:24.680 --> 06:30.080 of the count before entering the loop that iterate until it reaches the value 10000 as we saw previously 06:30.080 --> 06:35.360 B go scheduler we'll try to run the content of the go routines using as many OS threads as you can configured 06:35.360 --> 06:42.440 by using the Go Max proc configuration in my computer it set to 4 because my computer has 4 course but 06:42.440 --> 06:47.210 the point is that we can see that a lot of things can happen after launching a go routine or ten thousand 06:47.330 --> 06:53.630 and the next execution line but what about its uses of new taxes I show you the code which you can use 06:53.630 --> 07:00.950 for this let's create another folder and name it as locks underscore Singleton and within this we create 07:00.950 --> 07:11.610 two files Singleton Dok Go and Singleton test dot go file open the Singleton dot go file and add the 07:11.610 --> 07:18.840 code which will be explaining now similarly to the Singleton test dot go file we use the same test we 07:18.840 --> 07:20.370 used previously. 07:20.370 --> 07:26.120 Let's get back to Singleton dot go and try to understand the code we wrote here in this case the code 07:26.120 --> 07:31.970 is much leaner as we saw previously we can embed the new text within the Singleton structure the count 07:32.030 --> 07:36.770 is also held in the account field and the add one and get count methods lock and unlock the values to 07:36.770 --> 07:38.070 be concurrently safe. 07:38.090 --> 07:43.190 One more thing in this Singleton instance we're using the RW mutates type instead of the already known 07:43.190 --> 07:45.410 sync dot mutates type. 07:45.410 --> 07:50.270 The main difference here is that the RW mistakes typos two types of locks are read lock in a right lock 07:51.060 --> 07:56.240 the read lock executed by calling the R lock method only whites have a right lock is currently active 07:56.960 --> 08:02.450 at the same time it only blocks a right lock so that many read actions can be done in parallel it makes 08:02.450 --> 08:07.070 a lot of sense we don't want to block a go routine that wants to read a value just because another go 08:07.070 --> 08:13.190 routine is also reading the value it won't change the sync dot r w new text types helps us to achieve 08:13.190 --> 08:19.630 this logic in our code that's over this video in this section we've seen how to write a concurrent Singleton 08:19.630 --> 08:25.420 using new Texas and channels while the channels example was more complex it also shows the core power 08:25.420 --> 08:30.460 of goes concurrency as you can achieve complex levels of event driven architectures by simply using 08:30.460 --> 08:35.890 channels just keep in mind that if you haven't written concurrent code in the past it can take some 08:35.890 --> 08:40.660 time to start thinking concurrently in a comfortable way but it's nothing that practice cannot solve 08:41.050 --> 08:46.180 we've seen the importance of design and concurrent apps to achieve parallelism in our programs we've 08:46.180 --> 08:51.250 dealt with most of those primitives to write concurrent applications and now we can write common concurrent 08:51.250 --> 08:56.890 design patterns in the next section we'll be learning about the barrier future and pipeline design patterns.