Skip to content

Commit 13a7e2a

Browse files
committed
add chapter 10
1 parent dc861f6 commit 13a7e2a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+3583
-5
lines changed

.DS_Store

0 Bytes
Binary file not shown.
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
use std::sync::{mpsc::channel, Arc};
2+
use std::thread;
3+
4+
use parking_lot::RwLock;
5+
use parking_lot::{FairMutex, Mutex, Once, ReentrantMutex};
6+
7+
pub fn mutex_example() {
8+
const N: usize = 10;
9+
10+
let data = Arc::new(Mutex::new(0));
11+
let data2 = &data.clone();
12+
13+
let (tx, rx) = channel();
14+
for _ in 0..10 {
15+
let (data, tx) = (Arc::clone(&data), tx.clone());
16+
thread::spawn(move || {
17+
// The shared state can only be accessed once the lock is held.
18+
// Our non-atomic increment is safe because we're the only thread
19+
// which can access the shared state when the lock is held.
20+
let mut data = data.lock();
21+
*data += 1;
22+
if *data == N {
23+
tx.send(()).unwrap();
24+
}
25+
// the lock is unlocked here when `data` goes out of scope.
26+
});
27+
}
28+
29+
rx.recv().unwrap();
30+
31+
println!("mutex_example: {}", data2.lock());
32+
}
33+
34+
pub fn mutex_example2() {
35+
const N: usize = 10;
36+
37+
let mutex = Arc::new(Mutex::new(()));
38+
39+
let handles: Vec<_> = (0..N)
40+
.map(|i| {
41+
let mutex = Arc::clone(&mutex);
42+
thread::spawn(move || {
43+
let _lock = mutex.lock();
44+
println!("thread {} done", i);
45+
})
46+
})
47+
.collect();
48+
49+
for handle in handles {
50+
handle.join().unwrap();
51+
}
52+
53+
println!("mutex_example2: done");
54+
}
55+
56+
pub fn fairmutex_example() {
57+
const N: usize = 10;
58+
59+
let data = Arc::new(FairMutex::new(0));
60+
61+
let (tx, rx) = channel();
62+
for _ in 0..10 {
63+
let (data, tx) = (Arc::clone(&data), tx.clone());
64+
thread::spawn(move || {
65+
// The shared state can only be accessed once the lock is held.
66+
// Our non-atomic increment is safe because we're the only thread
67+
// which can access the shared state when the lock is held.
68+
let mut data = data.lock();
69+
*data += 1;
70+
if *data == N {
71+
tx.send(()).unwrap();
72+
}
73+
// the lock is unlocked here when `data` goes out of scope.
74+
});
75+
}
76+
77+
rx.recv().unwrap();
78+
79+
println!("fairmutex_example: done");
80+
}
81+
82+
pub fn rwmutex_example() {
83+
const N: usize = 10;
84+
85+
let lock = Arc::new(RwLock::new(5));
86+
87+
let handles: Vec<_> = (0..N)
88+
.map(|i| {
89+
let lock = Arc::clone(&lock);
90+
thread::spawn(move || {
91+
if i % 2 == 0 {
92+
let mut num = lock.write();
93+
*num += 1;
94+
} else {
95+
let num = lock.read();
96+
println!("thread {} read {}", i, num);
97+
}
98+
})
99+
})
100+
.collect();
101+
102+
for handle in handles {
103+
handle.join().unwrap();
104+
}
105+
106+
println!("rwmutex_example: {}", lock.read());
107+
}
108+
pub fn reentrantmutex_example() {
109+
let lock = ReentrantMutex::new(());
110+
111+
reentrant(&lock, 10);
112+
113+
println!("reentrantMutex_example: done");
114+
}
115+
116+
fn reentrant(lock: &ReentrantMutex<()>, i: usize) {
117+
if i == 0 {
118+
return;
119+
}
120+
121+
let _lock = lock.lock();
122+
reentrant(lock, i - 1);
123+
}
124+
125+
pub fn once_example() {
126+
static mut VAL: usize = 0;
127+
static INIT: Once = Once::new();
128+
fn get_cached_val() -> usize {
129+
unsafe {
130+
INIT.call_once(|| {
131+
println!("initializing once");
132+
thread::sleep(std::time::Duration::from_secs(1));
133+
VAL = 100;
134+
});
135+
VAL
136+
}
137+
}
138+
139+
140+
let handle = thread::spawn(|| {
141+
println!("thread 1 get_cached_val: {}", get_cached_val());
142+
});
143+
144+
println!("get_cached_val: {}", get_cached_val());
145+
146+
handle.join().unwrap();
147+
}
148+
149+
150+
pub fn condvar_example() {
151+
use std::sync::Condvar;
152+
use std::sync::Mutex;
153+
154+
let pair = Arc::new((Mutex::new(false), Condvar::new()));
155+
let pair2 = Arc::clone(&pair);
156+
157+
thread::spawn(move || {
158+
let (lock, cvar) = &*pair2;
159+
let mut started = lock.lock().unwrap();
160+
*started = true;
161+
cvar.notify_one();
162+
});
163+
164+
let (lock, cvar) = &*pair;
165+
let mut started = lock.lock().unwrap();
166+
while !*started {
167+
started = cvar.wait(started).unwrap(); // block until notified
168+
}
169+
println!("condvar_example: done");
170+
}
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
use std::sync::{mpsc::channel, Arc};
2+
use std::thread;
3+
4+
use parking_lot::RwLock;
5+
use parking_lot::{FairMutex, Mutex, Once, ReentrantMutex};
6+
7+
pub fn mutex_example() {
8+
const N: usize = 10;
9+
10+
let data = Arc::new(Mutex::new(0));
11+
let data2 = &data.clone();
12+
13+
let (tx, rx) = channel();
14+
for _ in 0..10 {
15+
let (data, tx) = (Arc::clone(&data), tx.clone());
16+
thread::spawn(move || {
17+
// The shared state can only be accessed once the lock is held.
18+
// Our non-atomic increment is safe because we're the only thread
19+
// which can access the shared state when the lock is held.
20+
let mut data = data.lock();
21+
*data += 1;
22+
if *data == N {
23+
tx.send(()).unwrap();
24+
}
25+
// the lock is unlocked here when `data` goes out of scope.
26+
});
27+
}
28+
29+
rx.recv().unwrap();
30+
31+
println!("mutex_example: {}", data2.lock());
32+
}
33+
34+
pub fn mutex_example2() {
35+
const N: usize = 10;
36+
37+
let mutex = Arc::new(Mutex::new(()));
38+
39+
let handles: Vec<_> = (0..N)
40+
.map(|i| {
41+
let mutex = Arc::clone(&mutex);
42+
thread::spawn(move || {
43+
let _lock = mutex.lock();
44+
println!("thread {} done", i);
45+
})
46+
})
47+
.collect();
48+
49+
for handle in handles {
50+
handle.join().unwrap();
51+
}
52+
53+
println!("mutex_example2: done");
54+
}
55+
56+
pub fn mutex_example3() {
57+
58+
}
59+
60+
61+
pub fn fairmutex_example() {
62+
const N: usize = 10;
63+
64+
let data = Arc::new(FairMutex::new(0));
65+
66+
let (tx, rx) = channel();
67+
for _ in 0..10 {
68+
let (data, tx) = (Arc::clone(&data), tx.clone());
69+
thread::spawn(move || {
70+
// The shared state can only be accessed once the lock is held.
71+
// Our non-atomic increment is safe because we're the only thread
72+
// which can access the shared state when the lock is held.
73+
let mut data = data.lock();
74+
*data += 1;
75+
if *data == N {
76+
tx.send(()).unwrap();
77+
}
78+
// the lock is unlocked here when `data` goes out of scope.
79+
});
80+
}
81+
82+
rx.recv().unwrap();
83+
84+
println!("fairmutex_example: done");
85+
}
86+
87+
pub fn rwmutex_example() {
88+
const N: usize = 10;
89+
90+
let lock = Arc::new(RwLock::new(5));
91+
92+
let handles: Vec<_> = (0..N)
93+
.map(|i| {
94+
let lock = Arc::clone(&lock);
95+
thread::spawn(move || {
96+
if i % 2 == 0 {
97+
let mut num = lock.write();
98+
*num += 1;
99+
} else {
100+
let num = lock.read();
101+
println!("thread {} read {}", i, num);
102+
}
103+
})
104+
})
105+
.collect();
106+
107+
for handle in handles {
108+
handle.join().unwrap();
109+
}
110+
111+
println!("rwmutex_example: {}", lock.read());
112+
}
113+
pub fn reentrantmutex_example() {
114+
let lock = ReentrantMutex::new(());
115+
116+
reentrant(&lock, 10);
117+
118+
println!("reentrantMutex_example: done");
119+
}
120+
121+
fn reentrant(lock: &ReentrantMutex<()>, i: usize) {
122+
if i == 0 {
123+
return;
124+
}
125+
126+
let _lock = lock.lock();
127+
reentrant(lock, i - 1);
128+
}
129+
130+
pub fn once_example() {
131+
static mut VAL: usize = 0;
132+
static INIT: Once = Once::new();
133+
fn get_cached_val() -> usize {
134+
unsafe {
135+
INIT.call_once(|| {
136+
println!("initializing once");
137+
thread::sleep(std::time::Duration::from_secs(1));
138+
VAL = 100;
139+
});
140+
VAL
141+
}
142+
}
143+
144+
145+
let handle = thread::spawn(|| {
146+
println!("thread 1 get_cached_val: {}", get_cached_val());
147+
});
148+
149+
println!("get_cached_val: {}", get_cached_val());
150+
151+
handle.join().unwrap();
152+
}
153+
154+
155+
pub fn condvar_example() {
156+
use std::sync::Condvar;
157+
use std::sync::Mutex;
158+
159+
let pair = Arc::new((Mutex::new(false), Condvar::new()));
160+
let pair2 = Arc::clone(&pair);
161+
162+
thread::spawn(move || {
163+
let (lock, cvar) = &*pair2;
164+
let mut started = lock.lock().unwrap();
165+
*started = true;
166+
cvar.notify_one();
167+
});
168+
169+
let (lock, cvar) = &*pair;
170+
let mut started = lock.lock().unwrap();
171+
while !*started {
172+
started = cvar.wait(started).unwrap(); // block until notified
173+
}
174+
println!("condvar_example: done");
175+
}

0 commit comments

Comments
 (0)