1 00:00:00,000 --> 00:00:07,133 [No Audio] 2 00:00:07,134 --> 00:00:09,480 In the previous tutorial, we have started our 3 00:00:09,481 --> 00:00:11,580 discussion of the threads, and we learned 4 00:00:11,610 --> 00:00:14,070 about the basics. In this tutorial, we will 5 00:00:14,071 --> 00:00:16,230 learn multiple threads and see concepts 6 00:00:16,231 --> 00:00:18,570 related to the issue of ownership. Let's 7 00:00:18,571 --> 00:00:20,760 start with an example. I haven't first bring 8 00:00:20,761 --> 00:00:22,500 the relevant modules into scope. 9 00:00:22,501 --> 00:00:29,970 [No Audio] 10 00:00:29,971 --> 00:00:31,966 I will next create a vector of threads. 11 00:00:31,967 --> 00:00:36,500 [No Audio] 12 00:00:36,501 --> 00:00:38,640 The type will be inferred by the Rust compiler 13 00:00:38,641 --> 00:00:41,250 when I assign some values to the vector. 14 00:00:41,670 --> 00:00:43,920 Next, I want to create 10 threads all 15 00:00:43,921 --> 00:00:46,350 containing the same code. So I will include a 16 00:00:46,351 --> 00:00:48,690 for loop which will iterate 10 times. 17 00:00:48,691 --> 00:00:54,090 [No Audio] 18 00:00:54,091 --> 00:00:56,550 Inside the loop, I will push a newly created 19 00:00:56,551 --> 00:00:57,870 thread inside the vector. 20 00:00:57,871 --> 00:01:03,000 [No Audio] 21 00:01:03,001 --> 00:01:05,850 Next, I will spawn a thread, and we'll include 22 00:01:05,880 --> 00:01:08,700 a simple print statement inside the body of the thread. 23 00:01:08,701 --> 00:01:16,170 [No Audio] 24 00:01:16,171 --> 00:01:18,270 The compiler is not happy in this case, it 25 00:01:18,271 --> 00:01:20,580 says closure may outlive the current 26 00:01:20,581 --> 00:01:23,850 function, but it borrows i, which is owned by 27 00:01:23,851 --> 00:01:26,130 the current function, and may out live to 28 00:01:26,131 --> 00:01:29,310 borrowed value i. Now let us see what does it 29 00:01:29,311 --> 00:01:32,430 mean. If we inspect the code, we may note 30 00:01:32,431 --> 00:01:34,980 that the variable i which is used with the 31 00:01:35,010 --> 00:01:37,950 for loop is part of the main thread, and is 32 00:01:37,951 --> 00:01:40,110 not part of the thread that we are creating. 33 00:01:40,140 --> 00:01:43,110 This means that the variable is not, is not 34 00:01:43,111 --> 00:01:45,750 part of the thread. Moreover, the closure 35 00:01:45,751 --> 00:01:48,030 inside the thread takes no arguments, which 36 00:01:48,031 --> 00:01:50,670 means that we are not using any data from the 37 00:01:50,671 --> 00:01:54,000 main thread in the spawn threads code. To 38 00:01:54,001 --> 00:01:56,160 use data from the main thread in the spawn 39 00:01:56,161 --> 00:01:58,860 thread, the spawn thread closure must capture 40 00:01:58,861 --> 00:02:01,890 the values it needs. Since we are not sure 41 00:02:01,920 --> 00:02:04,230 that the thread will live long enough as the 42 00:02:04,231 --> 00:02:06,780 main, therefore, to avoid possible lifetime 43 00:02:06,781 --> 00:02:08,729 issues, the Rust demands that the value may 44 00:02:08,730 --> 00:02:10,830 be moved inside the closure which resides 45 00:02:10,831 --> 00:02:13,890 inside the thread. This can be done with the 46 00:02:13,891 --> 00:02:16,266 help of the move keyword, let me add it. 47 00:02:16,267 --> 00:02:18,933 [No Audio] 48 00:02:18,934 --> 00:02:21,570 This means now that the individual value of i in 49 00:02:21,571 --> 00:02:23,070 each iteration of the loop will be 50 00:02:23,071 --> 00:02:25,470 transferred to inside the thread, and now the 51 00:02:25,471 --> 00:02:28,020 thread is is basically in charge of these 52 00:02:28,021 --> 00:02:30,993 values. Let us execute the code now a few times. 53 00:02:30,994 --> 00:02:38,550 [No Audio] 54 00:02:38,551 --> 00:02:40,470 You may note that it is not necessity, 55 00:02:40,471 --> 00:02:42,390 necessity that all the threads are being 56 00:02:42,391 --> 00:02:45,000 created. This is because some of the of the 57 00:02:45,001 --> 00:02:47,610 threads did not get a chance, to make sure 58 00:02:47,611 --> 00:02:49,650 that all the threads get a chance to execute, 59 00:02:49,680 --> 00:02:51,810 we will use the joint function in the main. 60 00:02:52,200 --> 00:02:54,480 Since there are 10 threads, so I will call the 61 00:02:54,481 --> 00:02:57,900 joint for each of the threads. I will include 62 00:02:57,901 --> 00:03:00,240 a for loop which will iterate as many times 63 00:03:00,241 --> 00:03:02,666 as there are threads in the thread_vec. 64 00:03:02,667 --> 00:03:09,360 [No Audio] 65 00:03:09,361 --> 00:03:11,370 During each iteration, I will call the join 66 00:03:11,371 --> 00:03:13,560 on the variable of i, which is assuming 67 00:03:13,561 --> 00:03:15,840 values from the thread_vec, which 68 00:03:15,841 --> 00:03:17,880 contains the threads that we have created 69 00:03:17,881 --> 00:03:19,200 using the code above. 70 00:03:19,201 --> 00:03:22,133 [No Audio] 71 00:03:22,134 --> 00:03:24,150 Let's execute the code a few times. 72 00:03:24,151 --> 00:03:32,280 [No Audio] 73 00:03:32,281 --> 00:03:34,620 You may note that each time all the threads 74 00:03:34,621 --> 00:03:37,230 are created and finished. However, it is not 75 00:03:37,231 --> 00:03:39,390 necessity that they will be created in the 76 00:03:39,391 --> 00:03:42,000 exact same order. The summary is that the 77 00:03:42,001 --> 00:03:44,430 move keyword is used to take ownership of the 78 00:03:44,431 --> 00:03:46,590 values that the closure uses from its 79 00:03:46,591 --> 00:03:49,290 environment, and we will need it in case of 80 00:03:49,291 --> 00:03:51,330 threads, so that they are able to take 81 00:03:51,360 --> 00:03:53,430 ownership of the values from the environment. 82 00:03:54,360 --> 00:03:56,466 Let us cover some more concepts, 83 00:03:56,467 --> 00:03:58,500 but first I will comment out the code. 84 00:03:58,501 --> 00:04:03,333 [No Audio] 85 00:04:03,334 --> 00:04:04,837 Let me define a vector first. 86 00:04:04,838 --> 00:04:12,510 [No Audio] 87 00:04:12,511 --> 00:04:15,240 Next I will create a thread and we'll assign 88 00:04:15,270 --> 00:04:16,697 it to the variable. 89 00:04:16,698 --> 00:04:20,700 [No Audio] 90 00:04:20,701 --> 00:04:21,766 Inside the thread I will 91 00:04:21,767 --> 00:04:23,910 use the variable v inside the print statement, 92 00:04:23,911 --> 00:04:25,830 so I will add a print statement, and we'll 93 00:04:25,831 --> 00:04:28,260 make sure that I move the variable v inside. 94 00:04:28,261 --> 00:04:32,820 [No Audio] 95 00:04:32,821 --> 00:04:35,190 Outside the thread, I will first call join on 96 00:04:35,191 --> 00:04:37,410 the threads to make sure that it gets a 97 00:04:37,411 --> 00:04:39,033 chance of being executed. 98 00:04:39,034 --> 00:04:42,535 [No Audio] 99 00:04:42,536 --> 00:04:43,600 This works fine. 100 00:04:43,933 --> 00:04:47,250 But now let me call a drop on the 101 00:04:47,251 --> 00:04:48,930 variable v after the thread. 102 00:04:48,931 --> 00:04:52,100 [No Audio] 103 00:04:52,101 --> 00:04:53,266 There is an error message 104 00:04:53,518 --> 00:04:54,990 you may have already guessed 105 00:04:54,991 --> 00:04:57,210 the error but let us look at the details, it 106 00:04:57,211 --> 00:05:00,420 says, use of moved value v. It further 107 00:05:00,421 --> 00:05:04,300 says, move occurs because we have typed vec i32. 108 00:05:04,301 --> 00:05:06,400 Which does not implement a copy trait. 109 00:05:06,401 --> 00:05:08,880 The error in this case is that if the thread 110 00:05:08,881 --> 00:05:11,760 is scheduled to be executed after this line 111 00:05:11,790 --> 00:05:14,160 in the main, then there will be potential 112 00:05:14,161 --> 00:05:15,870 issues because the thread is using the 113 00:05:15,871 --> 00:05:18,150 variable v which does not exist. The Rust 114 00:05:18,151 --> 00:05:21,720 therefore rightly complain. Okay, what if I 115 00:05:21,721 --> 00:05:23,700 initialize a primitive variable which has a 116 00:05:23,701 --> 00:05:26,970 copy trait and then I drop it, I will define 117 00:05:26,971 --> 00:05:29,520 a variable x and we'll initialize it from 118 00:05:29,521 --> 00:05:32,190 some suitable value and then I will use it 119 00:05:32,191 --> 00:05:34,466 inside the print statement included in the thread. 120 00:05:34,467 --> 00:05:39,266 [No Audio] 121 00:05:39,267 --> 00:05:41,070 Finally, I will pass it to the drop 122 00:05:41,071 --> 00:05:44,820 function. Now, you may notice that this code 123 00:05:44,821 --> 00:05:47,220 is perfectly fine. The reason behind this is 124 00:05:47,221 --> 00:05:49,830 that the drop does not work for the copy 125 00:05:49,831 --> 00:05:52,560 types. This means that the drop does not add 126 00:05:52,561 --> 00:05:54,870 the scope of a primitive variable. Therefore, 127 00:05:54,871 --> 00:05:57,510 the variable x remains there and there are no 128 00:05:57,511 --> 00:06:00,630 errors. Now some of you may be asking that 129 00:06:00,631 --> 00:06:03,120 if that drop cannot work with the primitive 130 00:06:03,121 --> 00:06:05,400 types, then how we can drop a primitive 131 00:06:05,401 --> 00:06:08,130 variable. The only meaningful way you can do 132 00:06:08,131 --> 00:06:10,890 it is to let the primitive variable fall out 133 00:06:10,891 --> 00:06:12,840 of scope in which it is defined. For 134 00:06:12,841 --> 00:06:15,480 instance, if I enclose the variable x inside 135 00:06:15,481 --> 00:06:18,690 brackets, then it will reside inside this and 136 00:06:18,691 --> 00:06:20,760 therefore it is not available to the thread. 137 00:06:21,000 --> 00:06:23,280 The final point to note is that the move is 138 00:06:23,281 --> 00:06:25,400 required for both the primitive and 139 00:06:25,401 --> 00:06:28,230 non-primitive types in the closure to thread. 140 00:06:28,380 --> 00:06:30,780 However, the primitive variables are being 141 00:06:30,781 --> 00:06:33,450 copied, while the non-primitive types are not 142 00:06:33,451 --> 00:06:35,790 copied, but their ownership is rather being 143 00:06:35,791 --> 00:06:38,100 transferred. To see this I will add a couple 144 00:06:38,101 --> 00:06:39,780 of print statements after the thread 145 00:06:39,781 --> 00:06:46,770 [No Audio] 146 00:06:46,771 --> 00:06:48,750 You may note that, the variable x has no 147 00:06:48,751 --> 00:06:51,870 issues, but the variable v has some errors. 148 00:06:52,110 --> 00:06:54,240 In summary, the move with the closure has 149 00:06:54,241 --> 00:06:56,310 different effects for both the primitives and 150 00:06:56,311 --> 00:06:59,010 non primitive variables. Okay with this we 151 00:06:59,011 --> 00:07:01,170 end this tutorial. See you again and until 152 00:07:01,171 --> 00:07:03,466 next tutoriall, happy Rust programming. 153 00:07:03,467 --> 00:07:08,200 [No Audio]