传送门:
深入浅出Rust(第一部分-1)
深入浅出Rust(第一部分-2)
深入浅出Rust(第二部分-1)
深入浅出Rust(第二部分-2)
深入浅出Rust(第三部分-1)
深入浅出Rust(第三部分-2)
深入浅出Rust(第四部分)
深入浅出Rust(第五部分)
第四部分 - 线程安全
Rust在编译器层面做了很多工作,进而在编译过程就发现和阻止线程不安全的情形
第27章 线程安全
1. 什么是线程
2. 启动线程
thread::spawn(MOVE ||{
//线程内部逻辑
});
相当于做了闭包代码块
Thead模块常用API:
- thread::sleep(dur: Duration)
- thread::yield_now()
- thread::current()
- thread::park()
- thread::Thread::unpark(&self)
3. 避免数据竞争
直接传mut变量,copy类型进去,都会造成编译错误.
4. send & Sync
Rust正是通过这两个特殊的trait,对线程安全进行了控制
pub fn spawn<F,T>(f: F) -> JoinHandle<T>
where F: FnOne() -> T, F:Send + 'static, T: Send +'static
从spawn的函数签名可以参数,F和T需要满足Send trait,因此在线程间传递所有权会发生安全问题的类型,Rust就能检测出来.
第28章 详解Send和Sync
1. 什么是Send
- Send trait满足不同线程间传递所有权是安全的
- 包括基本类型,内部不含引用的类型(string),泛型参数满足的(Cell<T>,RefCell<T>,Mutex<T>)
- 不包括RC<T>
2. 什么是Sync
- Sync trait满足不同线程使用&T访问同一变量
- 包括基本类型,泛型参数满足的(Box<T>,Vec<T>,Mutex<T>)
- 不包括Cell<T>,RefCell<T>
3. 自动推理
- 实际上 Send和Sync都是std::marker模块的特殊trait,用户不用手写impl,而是编译器自动完成
- 如果要自己写,一定要配合unsafe关键字,并且自己保证其安全性
第29章 状态共享
1. ARC
- Arc是Rc的线程安全版本
2. Mutex(重点)
- Mutex提供安全的内部可变性(通过lock()调用)
- lock()方法返回LockResult类型,
type LockResult<Guard> = Result<Guard, PoisonError<Guard>>;
如果lock过程发生了panic,那么这个Mutex则变为"有毒"状态.
3. RwLock
- RwLock和使用类似Mutex,相对来说,更不严格一点,可以通过read实现共享,write实现独占.
4. Atomic
- Atomic系列类型提供了"原子操作",因此他们都是符合Sync的,可以在多线程间共享使用.
- 修改时要用fetch_add()和fetch_sub()实现原子化的数据增减,而load,store本身虽然原子化,但是无法保证两个操作之间的原子化.
5. 死锁
- rust并不保证线程间不出现死锁,这个需要程序员自行完善逻辑
6. Barrier
- Barrier类似waitgroup,当条件完全满足才能继续
7. Condvar(重点)
- Condvar通常与Mutex配套使用,用来在线程之前进行消息传递,从而进行手工同步
8. 全局变量
- 全局变量显然不适合用在多线程里,太容易造成线程不安全了.
- mut全局变量基本无法满足Send,Sync约束
- 可以用atomic型全局变量(限定为简单的i32)
9. 线程局部存储
- threalocal!{}宏声明,××.with{}限定使用范围.
- java也一样这么搞的
第30章 管道
显然,Rust的channel比起Go,还是有差距的.
1. 异步管道
- 异步管道(std::sync::mpsc::channel),实现管道的异步读写(不需要考虑管道本身大小)
- Send和Receiver都必须满足T: Send约束.
- 可以实现多发单收
2. 同步管道
- 异步管道(std::sync::mpsc::sync_channel),实现管道的同步读写(管道大小为1)
第31章 第三方并行开发库
1. threadpool
- new出大小,execute执行
2. scoped-threadpool
- 线程内部直接使用&mut访问父线程变量,而不需用Arc包装
3. parking_lot
- 实现另外一套同步原语(Mutex,CondVar)
4. crossbeam
- 实现了双端管道
5. rayon
- 实现了并行迭代器和join()