rust_memory_safety_examples/
data_race_prevention.rs1use std::sync::{Arc, Mutex, RwLock};
4use std::thread;
5
6pub fn safe_concurrent_counter() {
43 let counter = Arc::new(Mutex::new(0));
44 let mut handles = vec![];
45
46 for _ in 0..10 {
47 let counter_clone = Arc::clone(&counter);
48 let handle = thread::spawn(move || {
49 for _ in 0..1000 {
50 let mut num = counter_clone.lock().unwrap();
51 *num += 1;
52 }
53 });
54 handles.push(handle);
55 }
56
57 for handle in handles {
58 handle.join().unwrap();
59 }
60
61 println!("Final counter value: {}", *counter.lock().unwrap());
62 }
64
65pub fn safe_read_write_access() {
67 let data = Arc::new(RwLock::new(vec![1, 2, 3]));
68 let mut handles = vec![];
69
70 for i in 0..5 {
72 let data_clone = Arc::clone(&data);
73 let handle = thread::spawn(move || {
74 let read_guard = data_clone.read().unwrap();
75 println!("Reader {}: {:?}", i, *read_guard);
76 });
77 handles.push(handle);
78 }
79
80 let data_clone = Arc::clone(&data);
82 let writer_handle = thread::spawn(move || {
83 let mut write_guard = data_clone.write().unwrap();
84 write_guard.push(4);
85 println!("Writer added element");
86 });
87 handles.push(writer_handle);
88
89 for handle in handles {
90 handle.join().unwrap();
91 }
92}
93
94struct SendableData {
100 value: i32,
101}
102
103struct NotSendable {
105 ptr: *mut i32, }
107
108pub fn thread_safety_enforced() {
110 let sendable = SendableData { value: 42 };
111
112 thread::spawn(move || {
114 println!("Value in thread: {}", sendable.value);
115 });
116
117 }
123
124use std::sync::mpsc;
126
127pub fn safe_message_passing() {
128 let (tx, rx) = mpsc::channel();
129
130 thread::spawn(move || {
131 for i in 0..5 {
132 tx.send(i).unwrap();
133 }
134 });
135
136 for received in rx {
137 println!("Received: {}", received);
138 }
139}
140
141use std::sync::atomic::{AtomicUsize, Ordering};
143
144pub fn safe_atomic_operations() {
145 let counter = Arc::new(AtomicUsize::new(0));
146 let mut handles = vec![];
147
148 for _ in 0..10 {
149 let counter_clone = Arc::clone(&counter);
150 let handle = thread::spawn(move || {
151 for _ in 0..1000 {
152 counter_clone.fetch_add(1, Ordering::SeqCst);
153 }
154 });
155 handles.push(handle);
156 }
157
158 for handle in handles {
159 handle.join().unwrap();
160 }
161
162 println!("Atomic counter: {}", counter.load(Ordering::SeqCst));
163}
164
165pub fn scoped_threads_safe() {
167 let mut data = vec![1, 2, 3];
168
169 thread::scope(|s| {
170 s.spawn(|| {
171 println!("Data length: {}", data.len());
173 });
174
175 s.spawn(|| {
176 println!("Data: {:?}", data);
177 });
178 });
179
180 data.push(4); }
183
184#[cfg(test)]
185mod tests {
186 use super::*;
187 use std::sync::atomic::Ordering;
188
189 #[test]
190 fn test_mutex_correctness() {
191 let counter = Arc::new(Mutex::new(0));
192 let mut handles = vec![];
193
194 for _ in 0..10 {
195 let counter_clone = Arc::clone(&counter);
196 let handle = thread::spawn(move || {
197 for _ in 0..100 {
198 *counter_clone.lock().unwrap() += 1;
199 }
200 });
201 handles.push(handle);
202 }
203
204 for handle in handles {
205 handle.join().unwrap();
206 }
207
208 assert_eq!(*counter.lock().unwrap(), 1000);
209 }
210
211 #[test]
212 fn test_atomic_correctness() {
213 let counter = Arc::new(AtomicUsize::new(0));
214 let mut handles = vec![];
215
216 for _ in 0..10 {
217 let counter_clone = Arc::clone(&counter);
218 let handle = thread::spawn(move || {
219 for _ in 0..100 {
220 counter_clone.fetch_add(1, Ordering::SeqCst);
221 }
222 });
223 handles.push(handle);
224 }
225
226 for handle in handles {
227 handle.join().unwrap();
228 }
229
230 assert_eq!(counter.load(Ordering::SeqCst), 1000);
231 }
232
233 #[test]
234 fn test_message_passing() {
235 let (tx, rx) = mpsc::channel();
236
237 thread::spawn(move || {
238 tx.send(42).unwrap();
239 });
240
241 let received = rx.recv().unwrap();
242 assert_eq!(received, 42);
243 }
244
245 #[test]
246 fn test_rwlock() {
247 let data = Arc::new(RwLock::new(vec![1, 2, 3]));
248 let data_clone = Arc::clone(&data);
249
250 let handle = thread::spawn(move || {
251 let read = data_clone.read().unwrap();
252 read.len()
253 });
254
255 let len = handle.join().unwrap();
256 assert_eq!(len, 3);
257 }
258}