2015-02-07 33 views
16

只是爲了得到更好的理解SendSync性狀,是有類型的,要麼例子:什麼是僅實現發送和同步之一的類型的示例?

  • 實施Send並沒有實現Sync
  • 執行Sync並且不執行Send
+0

[Huon Wilson關於'Send'和'Sync'的文章](https://huonw.github.io/blog/2015/02/some-notes-on-send-and-sync/)提到了一個假設垃圾收集的指針,'Gc ',作爲可能是'Sync'而不是'Send'的東西,儘管他沒有詳細說明。 – 2016-02-17 18:14:24

+1

@ JackO'Connor:給你吧:) – 2016-03-04 16:10:58

+0

@MatthieuM謝謝! :) – 2016-03-04 21:11:44

回答

9

CellRefCell實施Send但不Sync,因爲他們可以安全地在線程之間發送,但它們之間不共享。

+9

這是不正確的,AtomicIsize等其實執行發送。它沒有列在文檔頁面上,因爲實現是自動轉發的,不像Sync,它必須爲它們明確派生。然而,一個簡單的'let v:&Send =&AtomicIsize :: new(5);'表明它們實現了Send。 – wingedsubmariner 2015-02-09 16:44:17

+0

我已經編輯了@wingedsubmariner指出的錯誤部分。 – 2016-03-04 14:36:53

+0

你可以直接檢查類型是否實現了這些特徵([play example](https://play.rust-lang.org/?gist=c9f429c722da91aaf4a450eedaf16e21&version=stable)) – dhardy 2017-11-02 10:16:18

10

首先,它認識到,大多數結構(或枚舉)是很重要Send

  • 不包含任何引用任何結構可以Send + 'static
  • 包含有引用任何結構的'a下限期限可以是Send + 'a

其結果是,你通常會期望任何SyncstructSend也是如此,因爲Send是一個很容易達到的範圍(與Sync需要從多個線程進行安全併發修改的難度相比)要困難得多。


然而,沒有什麼能阻止一種類型的創建者特異性標記爲不Send。例如,讓我們復甦條件吧!

在Lisp中,條件的思想是爲給定條件設置一個處理程序(例如:FileNotFound),然後在堆棧深處滿足這個條件時調用你的處理程序。

你會如何在Rust中實現?

那麼,爲了保持線程的獨立性,你可以爲條件處理程序使用線程本地存儲(請參閱std::thread_local!)。每個條件將是條件處理程序的一個堆棧,要麼只調用最上面的一個,要麼從上面的一個迭代過程開始,直到一個成功。

但是,那麼,你會如何設置它們?

就我個人而言,我會用RAII!我會綁定線程本地堆棧中的條件處理程序並將其註冊到框架中(例如,使用一個入侵雙向鏈表作爲堆棧)。

這樣,當我完成後,條件處理程序會自動取消自己的註冊。

當然,系統必須爲用戶做出意想不到的事情(如將條件處理程序存儲在堆中,而不是按照創建的順序將其刪除),這就是爲什麼我們使用雙向鏈表的原因,以便處理程序可以根據需要從堆棧中間取消註冊。

因此,我們有:

struct ConditionHandler<T> { 
    handler: T, 
    prev: Option<*mut ConditionHandler<T>>, 
    next: Option<*mut ConditionHandler<T>>, 
} 

和「真實」的處理程序是由用戶通過T


這個處理程序是Sync

可能,取決於你如何創建它,但沒有理由不能創建一個處理程序,以便它的引用不能在多個線程之間共享。

注意:這些線程無法訪問其數據成員,它們是私有的,不一定是Sync

該處理程序是Send

除非特別注意,否則不會。

prevnext字段與併發訪問,即使在處理程序是,而另一個線程已獲得它(例如,另一個處理程序試圖註銷本身)的引用將被丟棄,然後這更糟糕的保護現在懸掛的引用會導致未定義的行爲。

注意:後一個問題意味着僅僅切換Option<*mut Handler<T>>AtomicPtr<ConditionHandler<T>>是不夠的;有關更多詳細信息,請參見Common Pitfalls in Writing Lock-Free Algorithms


有你有它:一個ConditionHandler<T>Sync如果TSync但絕不會Send(這是)。

爲了完整起見,許多類型的實施Send但不Sync(最Send類型,實際上):OptionVec例如。

+2

*讓我們復活吧!* - 你是一個瘋狂的,瘋狂的人。我喜歡它。 – Shepmaster 2016-03-04 16:30:43

相關問題