2017-03-01 49 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); 
    } 
} 
相关问题