Rust学习笔记

Rust编程语言入门教程课程笔记

参考教材: The Rust Programming Language (by Steve Klabnik and Carol Nichols, with contributions from the Rust Community)

Lecture 16: Fearless Concurrency

src/main.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use std::thread;
use std::time::Duration;
use std::sync::mpsc;
use std::sync::{Mutex, Arc};

fn main() {
//Using Threads to Run Code Simultaneously

//Creating a New Thread with spawn

let handle = thread::spawn(|| {
for i in 1..10 {
println!("hi number {} from the spawned thread!", i);
thread::sleep(Duration::from_millis(1));
}
});

for i in 1..5 {
println!("hi number {} from the main thread!", i);
thread::sleep(Duration::from_millis(1));
}
// output:
// hi number 1 from the main thread!
// hi number 1 from the spawned thread!
// hi number 2 from the main thread!
// hi number 2 from the spawned thread!
// hi number 3 from the main thread!
// hi number 3 from the spawned thread!
// hi number 4 from the main thread!
// hi number 4 from the spawned thread!

//In this run, the main thread printed first,
//even though the print statement from the spawned thread appears first in the code.
//And even though we told the spawned thread to print until i is 9,
//it only got to 5 before the main thread shut down.

//Waiting for All Threads to Finish Using join Handles
handle.join().unwrap();

let v = vec![1, 2, 3];
let handle = thread::spawn(move || {
println!("Here's a vector: {:?}", v);
});//move closure: v is moved into the closure

// drop(v); // oh no! v is moved into the thread

handle.join().unwrap();

//Using Message Passing to Transfer Data Between Threads
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
let val = String::from("hi");
// tx.send(val).unwrap();
tx.send(val).unwrap();
// println!("val is {}", val); // error: value borrowed here after move
});

let received = rx.recv().unwrap();//recv blocks the main thread’s execution and waits until a value is sent down the channel
println!("Got: {}", received);

//try_recv: without blocking

//Sending Multiple Values and Seeing the Receiver Waiting
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
let vals = vec![
String::from("hello"),
String::from("from"),
String::from("the"),
String::from("thread"),];
for val in vals {
tx.send(val).unwrap();
thread::sleep(Duration::from_secs(1));
}
});

for received in rx {
println!("Got: {}", received);
}

//Shared-State Concurrency
//Mutexes: Mutual Exclusion
//API: lock, unwrap, Mutex<T> (smart pointer)

let m = Mutex::new(5);
{
let mut num = m.lock().unwrap();
*num = 6;
// println!("m is {}", m); // error: cannot be formatted with the default formatter
}

println!("m is {:?}", m);

//Sharing a Mutex<T> Between Multiple Threads
let counter = Arc::new(Mutex::new(0));
//Arc<T> is an atomically reference counted type
//A: atomically, R: reference, C: counted
//API in Arc is the same as in Rc


let mut handles = vec![];

for _ in 0..10 {
let counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();

*num += 1;
});
handles.push(handle);
}

for handle in handles {
handle.join().unwrap();
}

println!("Result: {}", *counter.lock().unwrap());//Result: 10

//Extensible Concurrency with the Sync and Send Traits
//Send: ownership can be transferred between threads
//Sync: multiple threads can have references to the same value

//Implementing Send and Sync Manually Is Unsafe
}