1 00:00:06,600 --> 00:00:08,850 - Rust provides a simple API, 2 00:00:08,850 --> 00:00:12,060 which allows you to manage threads manually. 3 00:00:12,060 --> 00:00:15,480 All of the functions you need are in the std thread module. 4 00:00:15,480 --> 00:00:18,630 And the API allows you to spawn a thread, 5 00:00:18,630 --> 00:00:20,220 which means to create it. 6 00:00:20,220 --> 00:00:21,750 You can join the thread, 7 00:00:21,750 --> 00:00:23,850 which means to wait for it to finish. 8 00:00:23,850 --> 00:00:27,330 You can move data into a thread if it needs some context, 9 00:00:27,330 --> 00:00:30,300 and you can communicate data between threads. 10 00:00:30,300 --> 00:00:32,610 There's a mechanism we'll have a look at in this lesson 11 00:00:32,610 --> 00:00:35,130 called a channel like a pipeline 12 00:00:35,130 --> 00:00:36,870 which allows data from one thread 13 00:00:36,870 --> 00:00:38,400 to be sent into another one 14 00:00:38,400 --> 00:00:41,910 without having to worry about things like lock in. 15 00:00:41,910 --> 00:00:44,220 So that's the preferred way to communicate data 16 00:00:44,220 --> 00:00:47,400 between one thread and another using a channel 17 00:00:47,400 --> 00:00:48,840 as we shall see. 18 00:00:48,840 --> 00:00:50,760 Okay, so to spawn the thread 19 00:00:50,760 --> 00:00:52,950 you call the std thread spawn function, 20 00:00:52,950 --> 00:00:57,360 the spawn function in the thread module in the std create. 21 00:00:57,360 --> 00:00:59,940 And when you call the spawn function, 22 00:00:59,940 --> 00:01:01,860 you pass a closure as a parameter, 23 00:01:01,860 --> 00:01:05,313 a block of code to say run that code in a thread. 24 00:01:06,390 --> 00:01:08,940 Okay, so when you call the spawn function 25 00:01:08,940 --> 00:01:12,330 Rust creates a system thread on your operating system, 26 00:01:12,330 --> 00:01:15,960 and executes your closure code on that thread 27 00:01:15,960 --> 00:01:17,310 as you would expect. 28 00:01:17,310 --> 00:01:18,840 Here's a simple example, 29 00:01:18,840 --> 00:01:21,600 I called the thread spawn function, 30 00:01:21,600 --> 00:01:23,790 and I've given it a simple closure here. 31 00:01:23,790 --> 00:01:25,860 This closure will be executed 32 00:01:25,860 --> 00:01:28,710 on the other thread, on the other system thread. 33 00:01:28,710 --> 00:01:31,413 The main thread will continue to execute in parallel. 34 00:01:32,700 --> 00:01:36,180 Every thread that you create in Rust has a different id, 35 00:01:36,180 --> 00:01:37,767 and you can get the id like this, 36 00:01:37,767 --> 00:01:41,040 you can say thread::current, 37 00:01:41,040 --> 00:01:44,250 and then upon the object returned by the current function, 38 00:01:44,250 --> 00:01:48,000 you can say .id, and that can be useful for login purposes. 39 00:01:48,000 --> 00:01:51,060 You know, it's quite useful when you have a real system 40 00:01:51,060 --> 00:01:53,310 to log messages and the thread id 41 00:01:53,310 --> 00:01:55,440 can be useful to help you diagnose problems. 42 00:01:55,440 --> 00:01:58,170 If you have a problem, what thread did the problem occur on? 43 00:01:58,170 --> 00:01:59,373 The id gives you that. 44 00:02:00,240 --> 00:02:03,210 You can also tell a thread to sleep for specified duration, 45 00:02:03,210 --> 00:02:04,740 you call the thread sleep function, 46 00:02:04,740 --> 00:02:05,940 probably would've guessed that. 47 00:02:05,940 --> 00:02:07,500 You pass in a duration, 48 00:02:07,500 --> 00:02:09,450 there's actually a class, a structure, I should say, 49 00:02:09,450 --> 00:02:11,280 called duration, and it specifies 50 00:02:11,280 --> 00:02:14,523 how long you wanna wait for in seconds, for example. 51 00:02:15,390 --> 00:02:17,130 So it's actually quite straightforward, 52 00:02:17,130 --> 00:02:19,080 we'll have a look at an example. 53 00:02:19,080 --> 00:02:20,610 The project for this lesson 54 00:02:20,610 --> 00:02:23,583 is lesson 14 multithreading concurrency. 55 00:02:24,780 --> 00:02:28,380 Okay, so here it is, in the Rustdev folder, 56 00:02:28,380 --> 00:02:30,960 lesson 14 multithreading concurrency. 57 00:02:30,960 --> 00:02:34,860 So if you open that folder in the code editor, 58 00:02:34,860 --> 00:02:36,327 I'll tell you the files we're going to look at. 59 00:02:36,327 --> 00:02:39,540 For this demo, we're going to look at obviously the main.rs, 60 00:02:39,540 --> 00:02:40,860 which is our entry point, 61 00:02:40,860 --> 00:02:43,890 and the demo file, demo spawning threads, 62 00:02:43,890 --> 00:02:45,210 and then we'll run it. 63 00:02:45,210 --> 00:02:46,470 Okay, so let's take a look at the code 64 00:02:46,470 --> 00:02:48,090 and then we'll run it. 65 00:02:48,090 --> 00:02:52,410 Okay, here we are, so in the main entry code 66 00:02:52,410 --> 00:02:55,683 let's run the first demo, demo spawning threads, 67 00:02:56,541 --> 00:02:59,793 let's uncomment that, and it's here. 68 00:03:01,380 --> 00:03:03,780 So little message to welcome me in. 69 00:03:03,780 --> 00:03:08,780 Notice, I've imported the std thread module, 70 00:03:10,560 --> 00:03:13,083 so I can just use thread directly here. 71 00:03:14,340 --> 00:03:17,880 Obviously, if I hadn't imported std thread, 72 00:03:17,880 --> 00:03:19,440 I'd have to fully qualify it here, 73 00:03:19,440 --> 00:03:21,333 std thread and std thread, 74 00:03:25,290 --> 00:03:27,180 again in various other places as well. 75 00:03:27,180 --> 00:03:28,350 So it makes it easier 76 00:03:28,350 --> 00:03:30,663 if you just import it in the first place. 77 00:03:31,590 --> 00:03:34,230 Right, so when the application starts, 78 00:03:34,230 --> 00:03:36,480 the main thread will come in here, 79 00:03:36,480 --> 00:03:39,270 and the main thread will call this function, 80 00:03:39,270 --> 00:03:43,350 and that will cause a second thread to be created. 81 00:03:43,350 --> 00:03:45,570 It usually takes, you know, a few milliseconds 82 00:03:45,570 --> 00:03:48,210 for that other thread to actually get going. 83 00:03:48,210 --> 00:03:49,470 So it'll take a few milliseconds, 84 00:03:49,470 --> 00:03:51,870 but sooner rather than later 85 00:03:51,870 --> 00:03:56,670 this closure will be executed on a separate thread. 86 00:03:56,670 --> 00:03:58,230 And on that separate thread, 87 00:03:58,230 --> 00:04:00,120 oh, actually what I should say 88 00:04:00,120 --> 00:04:03,900 is the thread spawn function returns immediately. 89 00:04:03,900 --> 00:04:05,340 Okay, so as soon as you call it 90 00:04:05,340 --> 00:04:07,470 it'll kind of kick off this background thread, 91 00:04:07,470 --> 00:04:10,440 but the main thread will continue immediately 92 00:04:10,440 --> 00:04:13,410 to carry on with the rest of the function, okay. 93 00:04:13,410 --> 00:04:15,720 So the main thread will continue to execute this 94 00:04:15,720 --> 00:04:19,413 whilst the other thread is getting started. 95 00:04:20,460 --> 00:04:23,280 So when the other thread has been started 96 00:04:23,280 --> 00:04:25,680 kind of in parallel to the main thread, 97 00:04:25,680 --> 00:04:28,020 it loops around 10 times 98 00:04:28,020 --> 00:04:31,590 and it prints out thread current id. 99 00:04:31,590 --> 00:04:34,170 So we print out the current thread id 100 00:04:34,170 --> 00:04:36,450 using the debug formatter, 101 00:04:36,450 --> 00:04:39,660 and the loop counter 0 through to 10, 102 00:04:39,660 --> 00:04:41,940 and then we sleep for one second. 103 00:04:41,940 --> 00:04:44,970 Okay, so the background thread will sleep for 10 seconds, 104 00:04:44,970 --> 00:04:48,420 every one second, it'll output one, 105 00:04:48,420 --> 00:04:50,790 and then one second later it'll put two, 106 00:04:50,790 --> 00:04:52,980 and then one second later it'll output three. 107 00:04:52,980 --> 00:04:54,900 So this background thread 108 00:04:54,900 --> 00:04:56,913 is gonna take 10 seconds to finish. 109 00:04:58,560 --> 00:05:01,530 Okay, let's have a look at the main thread, 110 00:05:01,530 --> 00:05:03,720 the main thread will be continuing to process all this time, 111 00:05:03,720 --> 00:05:08,190 and that loops around five times on the main thread 112 00:05:08,190 --> 00:05:10,800 and it displays the thread id for the main thread. 113 00:05:10,800 --> 00:05:12,660 So we're gonna get two sets of messages 114 00:05:12,660 --> 00:05:14,190 being displayed here, 115 00:05:14,190 --> 00:05:16,293 the messages displayed by the main thread. 116 00:05:17,190 --> 00:05:18,873 Okay, and we can see the id, 117 00:05:19,710 --> 00:05:21,690 and interspersed with that 118 00:05:21,690 --> 00:05:24,120 'cause I've got a four second delay here. 119 00:05:24,120 --> 00:05:25,380 That's quite a long delay, isn't it? 120 00:05:25,380 --> 00:05:28,070 So what's gonna happen is this inner loop 121 00:05:28,070 --> 00:05:30,060 is gonna spin around quite quickly, 122 00:05:30,060 --> 00:05:31,890 there's gonna be a one second sleep. 123 00:05:31,890 --> 00:05:34,440 So that thing's going to loop around quite quickly. 124 00:05:35,510 --> 00:05:38,910 Every one second it will output another message like that, 125 00:05:38,910 --> 00:05:41,100 and then in a relatively slow loop 126 00:05:41,100 --> 00:05:42,720 on the outside, on the main thread, 127 00:05:42,720 --> 00:05:46,443 every four seconds the main thread will output a message. 128 00:05:47,550 --> 00:05:51,060 Okay, I'm just doing the maths here. 129 00:05:51,060 --> 00:05:54,003 This inner thread is going to take 10 seconds to finish. 130 00:05:55,530 --> 00:05:58,110 Okay, so that's gonna finish quite quickly. 131 00:05:58,110 --> 00:06:00,750 This main thread is going to take, 132 00:06:00,750 --> 00:06:02,560 if I'm looping around five times 133 00:06:03,900 --> 00:06:07,080 and each time I'm gonna basically sleep for four seconds, 134 00:06:07,080 --> 00:06:09,780 that's gonna take 20 seconds to complete. 135 00:06:09,780 --> 00:06:13,470 So this inner thread will complete within 10 seconds, 136 00:06:13,470 --> 00:06:15,900 and then terminate as soon as your code 137 00:06:15,900 --> 00:06:18,750 falls off the end of the closure, 138 00:06:18,750 --> 00:06:20,250 that's the end of that thread. 139 00:06:20,250 --> 00:06:25,170 The main thread will continue in its four second loop here 140 00:06:25,170 --> 00:06:29,790 to eventually print out 100 through to 105. 141 00:06:29,790 --> 00:06:31,650 I think that should make sense actually when we run it, 142 00:06:31,650 --> 00:06:33,250 let's have a quick look and see. 143 00:06:37,590 --> 00:06:40,593 Okay, so cargo run. 144 00:06:45,600 --> 00:06:48,933 So it's download independencies specified in my toml file. 145 00:06:50,940 --> 00:06:52,890 Okay, so notice the output, 146 00:06:52,890 --> 00:06:54,090 we've got two threads you can see. 147 00:06:54,090 --> 00:06:55,950 Thread one is the main thread, 148 00:06:55,950 --> 00:06:57,930 which is looping on four-second timer. 149 00:06:57,930 --> 00:07:00,420 Thread two is the background thread, 150 00:07:00,420 --> 00:07:02,553 and that looped around fairly quickly. 151 00:07:03,570 --> 00:07:06,540 Now, I'm still waiting for the outer thread, 152 00:07:06,540 --> 00:07:08,820 the main thread to reach 105, 153 00:07:08,820 --> 00:07:10,620 every four seconds it loops around again, 154 00:07:10,620 --> 00:07:14,763 and another four seconds, and then it terminates. 155 00:07:15,660 --> 00:07:18,600 Okay, so that actually makes sense, a simple example, 156 00:07:18,600 --> 00:07:21,390 but you can kind of see the dynamism of it. 157 00:07:21,390 --> 00:07:25,410 So the main thread came in, thread one as it turns out, 158 00:07:25,410 --> 00:07:27,010 it kicked off this other thread. 159 00:07:28,020 --> 00:07:30,570 It took a little while for this other thread to get started, 160 00:07:30,570 --> 00:07:33,963 so even though we started the other thread here, 161 00:07:34,920 --> 00:07:37,200 you notice that this main thread 162 00:07:37,200 --> 00:07:38,640 continued a little bit first, 163 00:07:38,640 --> 00:07:41,313 so the main thread managed to get this far, 164 00:07:43,740 --> 00:07:46,200 and it displayed its first value 100. 165 00:07:46,200 --> 00:07:47,220 It managed to get that far 166 00:07:47,220 --> 00:07:50,430 before this other thread managed to wipe its feet, 167 00:07:50,430 --> 00:07:52,050 and actually get started. 168 00:07:52,050 --> 00:07:54,930 And then this then looped around quite quickly, 169 00:07:54,930 --> 00:07:57,810 everyone second thread number two 170 00:07:57,810 --> 00:07:59,580 was displaying the number four. 171 00:07:59,580 --> 00:08:01,260 And then it was one second delay, number five, 172 00:08:01,260 --> 00:08:02,790 number six, number seven, number eight. 173 00:08:02,790 --> 00:08:05,070 And you can see because of the four second delay 174 00:08:05,070 --> 00:08:09,000 on the main thread, that's gonna quite a low periodicity. 175 00:08:09,000 --> 00:08:11,880 Whereas my inner thread with a one second delay 176 00:08:11,880 --> 00:08:13,430 is looping around more quickly. 177 00:08:14,910 --> 00:08:18,570 Right, so here's a secret. 178 00:08:18,570 --> 00:08:21,270 When I was writing this demo, I wanted to make, 179 00:08:21,270 --> 00:08:22,800 I haven't talked about how to wait 180 00:08:22,800 --> 00:08:24,690 for another thread to finish yet. 181 00:08:24,690 --> 00:08:26,340 So I was quite careful 182 00:08:26,340 --> 00:08:31,340 that this inner thread finished first, okay? 183 00:08:31,500 --> 00:08:33,060 And then this outer thread, 184 00:08:33,060 --> 00:08:34,980 as soon as this outer thread finished, 185 00:08:34,980 --> 00:08:36,930 then the application terminated. 186 00:08:36,930 --> 00:08:39,330 I was quite careful to make sure that this then, 187 00:08:39,330 --> 00:08:40,980 I didn't have to wait for this thing to finish, 188 00:08:40,980 --> 00:08:42,183 it finished first. 189 00:08:43,320 --> 00:08:45,030 So that as soon as my main thread finished, 190 00:08:45,030 --> 00:08:47,040 it was okay to finish the whole application. 191 00:08:47,040 --> 00:08:50,070 What we're going to look at in the next example 192 00:08:50,070 --> 00:08:55,070 is how to wait for a thread that's longer running than us. 193 00:08:55,170 --> 00:08:58,200 So the main thread would like to terminate more quickly, 194 00:08:58,200 --> 00:09:01,740 but the inner thread is taking longer. 195 00:09:01,740 --> 00:09:04,650 So we can say, let's wait for that other thread to finish 196 00:09:04,650 --> 00:09:06,090 before the main thread finishes. 197 00:09:06,090 --> 00:09:08,310 So that's coming up in the next example, 198 00:09:08,310 --> 00:09:10,530 it'll be an example of the join function. 199 00:09:10,530 --> 00:09:12,230 That's the next example coming up.