傳送門(mén):
深入淺出Rust(第一部分-1)
深入淺出Rust(第一部分-2)
深入淺出Rust(第二部分-1)
深入淺出Rust(第二部分-2)
深入淺出Rust(第三部分-1)
深入淺出Rust(第三部分-2)
深入淺出Rust(第四部分)
深入淺出Rust(第五部分)
第四部分 - 線程安全
Rust在編譯器層面做了很多工作,進(jìn)而在編譯過(guò)程就發(fā)現(xiàn)和阻止線程不安全的情形
第27章 線程安全
1. 什么是線程
2. 啟動(dòng)線程
thread::spawn(MOVE ||{
//線程內(nèi)部邏輯
});
相當(dāng)于做了閉包代碼塊
Thead模塊常用API:
- thread::sleep(dur: Duration)
- thread::yield_now()
- thread::current()
- thread::park()
- thread::Thread::unpark(&self)
3. 避免數(shù)據(jù)競(jìng)爭(zhēng)
直接傳mut變量,copy類(lèi)型進(jìn)去,都會(huì)造成編譯錯(cuò)誤.
4. send & Sync
Rust正是通過(guò)這兩個(gè)特殊的trait,對(duì)線程安全進(jìn)行了控制
pub fn spawn<F,T>(f: F) -> JoinHandle<T>
where F: FnOne() -> T, F:Send + 'static, T: Send +'static
從spawn的函數(shù)簽名可以參數(shù),F和T需要滿足Send trait,因此在線程間傳遞所有權(quán)會(huì)發(fā)生安全問(wèn)題的類(lèi)型,Rust就能檢測(cè)出來(lái).
第28章 詳解Send和Sync
1. 什么是Send
- Send trait滿足不同線程間傳遞所有權(quán)是安全的
- 包括基本類(lèi)型,內(nèi)部不含引用的類(lèi)型(string),泛型參數(shù)滿足的(Cell<T>,RefCell<T>,Mutex<T>)
- 不包括RC<T>
2. 什么是Sync
- Sync trait滿足不同線程使用&T訪問(wèn)同一變量
- 包括基本類(lèi)型,泛型參數(shù)滿足的(Box<T>,Vec<T>,Mutex<T>)
- 不包括Cell<T>,RefCell<T>
3. 自動(dòng)推理
- 實(shí)際上 Send和Sync都是std::marker模塊的特殊trait,用戶不用手寫(xiě)impl,而是編譯器自動(dòng)完成
- 如果要自己寫(xiě),一定要配合unsafe關(guān)鍵字,并且自己保證其安全性
第29章 狀態(tài)共享
1. ARC
- Arc是Rc的線程安全版本
29-1.png
2. Mutex(重點(diǎn))
- Mutex提供安全的內(nèi)部可變性(通過(guò)lock()調(diào)用)
- lock()方法返回LockResult類(lèi)型,
type LockResult<Guard> = Result<Guard, PoisonError<Guard>>;
如果lock過(guò)程發(fā)生了panic,那么這個(gè)Mutex則變?yōu)?有毒"狀態(tài).
3. RwLock
- RwLock和使用類(lèi)似Mutex,相對(duì)來(lái)說(shuō),更不嚴(yán)格一點(diǎn),可以通過(guò)read實(shí)現(xiàn)共享,write實(shí)現(xiàn)獨(dú)占.
4. Atomic
- Atomic系列類(lèi)型提供了"原子操作",因此他們都是符合Sync的,可以在多線程間共享使用.
- 修改時(shí)要用fetch_add()和fetch_sub()實(shí)現(xiàn)原子化的數(shù)據(jù)增減,而load,store本身雖然原子化,但是無(wú)法保證兩個(gè)操作之間的原子化.
5. 死鎖
- rust并不保證線程間不出現(xiàn)死鎖,這個(gè)需要程序員自行完善邏輯
6. Barrier
- Barrier類(lèi)似waitgroup,當(dāng)條件完全滿足才能繼續(xù)
7. Condvar(重點(diǎn))
- Condvar通常與Mutex配套使用,用來(lái)在線程之前進(jìn)行消息傳遞,從而進(jìn)行手工同步
29-2.png
8. 全局變量
- 全局變量顯然不適合用在多線程里,太容易造成線程不安全了.
- mut全局變量基本無(wú)法滿足Send,Sync約束
- 可以用atomic型全局變量(限定為簡(jiǎn)單的i32)
9. 線程局部存儲(chǔ)
- threalocal!{}宏聲明,××.with{}限定使用范圍.
- java也一樣這么搞的
第30章 管道
顯然,Rust的channel比起Go,還是有差距的.
1. 異步管道
- 異步管道(std::sync::mpsc::channel),實(shí)現(xiàn)管道的異步讀寫(xiě)(不需要考慮管道本身大小)
- Send和Receiver都必須滿足T: Send約束.
- 可以實(shí)現(xiàn)多發(fā)單收
2. 同步管道
- 異步管道(std::sync::mpsc::sync_channel),實(shí)現(xiàn)管道的同步讀寫(xiě)(管道大小為1)
第31章 第三方并行開(kāi)發(fā)庫(kù)
1. threadpool
- new出大小,execute執(zhí)行
2. scoped-threadpool
- 線程內(nèi)部直接使用&mut訪問(wèn)父線程變量,而不需用Arc包裝
3. parking_lot
- 實(shí)現(xiàn)另外一套同步原語(yǔ)(Mutex,CondVar)
4. crossbeam
- 實(shí)現(xiàn)了雙端管道
5. rayon
31-1.png
- 實(shí)現(xiàn)了并行迭代器和join()