2017-03-01 44 views
3

我有一個工作線程運行在一個循環中,有時會做工作。我想有一個經理線程keeps a watchful eye on whether the first thread has done any work recently從線程共享一個時間戳到另一個

我認爲最簡單的方法是擁有一個包含時間戳的變量;當工作線程執行某些工作時,它會將當前時間寫入變量,並且當管理線程想要檢查工作線程時,它會從變量中讀取時間並測量與當前時間的差異。

首先,這個變量需要是原子嗎?我的本能是在線程之間進行通信時使用原子,但在這種情況下,沒有讀 - 修改 - 寫週期,只有一個線程正在進行更新。時間值應該足夠小以適合一個單詞,因此也許不用擔心字詞撕裂。是否應該鼓勵在線程之間及時傳播?如果沒有,分享時間戳的正確方法是什麼?

其次,代表時間戳的合適類型是什麼,以及如何獲取它的實例? std :: time :: Instant似乎是明顯的選擇,但它不是同步或發送,而且我不知道如何擁有一個原子。有更好的選擇嗎?

+1

如果一個線程正在寫,這是絕對必須的原子或以其他方式同步。你也不一定需要時間戳;一個簡單的原子旗可以做,如果你想知道的是「自上次檢查後線程做了什麼?」。 –

回答

1

std::time::Instant actually does implement Send。您沒有看到在文檔中實現SendSync的所有類型;您只能看到負面實施(例如Rc)和顯式實施(例如Arc)。 SendSync使用了一種語言特性(在Rust 1.15.1中仍然不穩定),使得編譯器在自定義類型中實現它們(如果所有字段都實現該特性)(即,如果所有字段都是Send,則類型爲Send;同樣的與Sync)。明確的實現(必須標記爲unsafe,因爲特徵定義爲unsafe)存在以覆蓋負面實現(其根源是原始指針類型;其他負面實現完全是多餘的,但它們出於文檔目的) 。當然,當一個類型具有專用字段時,如果該類型實現Send和/或Sync,則不能通過查看文檔來判斷。最好的檢查方法是試着編譯一些需要它的代碼。

因此,如果你需要一個共享的,可變的Instant,只需使用Arc<Mutex<Instant>>

+0

這是一個關於同步和發送的巨大啓示!這是一個真正的恥辱,他們沒有包括在生成的文檔中,但我可以用它來處理它,使用你的編譯技巧。 –

+0

如果可能,我想避免互斥。經理線程掌握了大量時間,但工作線程可能會在每個循環計數的地方進行工作,所以我希望儘快分享數據。 –

2

我到目前爲止所做的是寫我自己的AtomicInstant。 Instant的內容是特定於平臺並且隱藏得很好的,但它可以轉換爲另一個Instant的偏移量,形式爲持續時間,然後可以轉換爲納秒計數。反過來,這可以被塞進一個大小,只要你測量的時間在你的機器的字大小方面不會太大(一天約2 ** 46納秒; 64位機可以測量大約350年)。這個轉換鏈可以全部顛倒以讀取一個值。

的代碼看起來是這樣的(可能有一點不同,因此有可能這是錯誤的):

struct AtomicInstant { 
    base: Instant, 
    offset: AtomicUsize, 
} 

impl AtomicInstant { 
    fn new(base: Instant) -> AtomicInstant { 
     AtomicInstant { 
      base: base, 
      offset: AtomicUsize::new(0), 
     } 
    } 

    fn load(&self, order: Ordering) -> Instant { 
     let offset_nanos = self.offset.load(order) as u64; 
     let secs = offset_nanos/1_000_000_000; 
     let subsec_nanos = (offset_nanos % 1_000_000_000) as u32; 
     let offset = Duration::new(secs, subsec_nanos); 
     return self.base + offset; 
    } 

    fn store(&self, val: Instant, order: Ordering) { 
     let offset = val - self.base; 
     let offset_nanos = offset.as_secs() * 1_000_000_000 + offset.subsec_nanos() as u64; 
     self.offset.store(offset_nanos as usize, order); 
    } 
} 
相關問題