2009-01-20 112 views
3

我有一些代码,将会从两个线程访问:多线程代码 - 力执行顺序


class Timer{ 
public: 
    void Start(){ 
     start_ = clock_->GetCurrentTime(); 
     running_ = true; 
    } 

    void Read(){ 
     if(running_){ 
     time_duration remaining = clock_->GetCurrentTime() - start_; 
     Actions(remaining) 
     } 
    } 

private: 
    void Actions(time_duration remaining); 
    time start_; 
    bool running; 
}; 

我看着在各个库提供一些其他的计时器,但没有发现任何适合我的要求,因此我滚动自己的...

Start()方法从一个线程被调用(仅一次)。 Read()方法在另一个线程中被非常快速地调用,调用将在Start()被调用之前开始。

显然,在设置running_标志之前,初始化start_变量之前是,这非常重要。这可以通过添加一个互斥体来获得,该互斥体在进入Start()方法时被抓住并且在Read()方法中检查running_之前抓取...但似乎没有必要。如果这里的一切按顺序执行,那就没有问题了。在另一个线程处于Start()路由中的时候,Read()会发生,并且从时钟获取时间,例如... Read()发生的速度足够快以至于它不是一个大不了。

反正,我一直在寻找一种方法来确保编译器/处理器将在它们上面列出的顺序执行

start_ = clock_->GetCurrentTime(); 
    running_ = true; 

指令。 (或者如果我忽略了别的东西)。

回答

1

为什么不摆脱“运行”标志并使用“start”变量是否为空作为条件?你没有指定一种语言,但是对于“开始”而言,某种挥发性标记也是一个好主意。这也假设“开始”可以被原子写入。例如:

class Timer{ 
public: 
    void Start(){ 
    start_ = clock_->GetCurrentTime(); 
    } 
    void Read(){ 
    if(nullptr != start_){ 
    time_duration remaining = clock_->GetCurrentTime() - start_; 
    Actions(remaining)  
    } 
} 
private: 
    void Actions(time_duration remaining); 
    volatile time start_; 
}; 
+0

这不起作用,因为start_不是一个小原子事物。 – teeks99 2009-01-20 21:55:21

0

我不确定我是否理解你的问题,但是我认为你想阻止在Start方法尚未设置(或尚未完全执行)时执行Read操作?

如果是这样的话,你不能通过使用AutoResetEvent或ManualResetEvent(取决于你想要的行为)来解决你的问题。

在Read方法中,您可以指定在Auto/ManualResetEvent尚未设置时Read方法应该等待,并且在Start方法结束时可以设置Event。

3

您需要使start_和running_volatile,然后在Start()两个分配之间引入一个内存屏障。

+0

我在想这些方面......但我正在寻找更多的细节。 所有编译器是否支持volatile?你知道关于记忆障碍的任何好文档吗? – teeks99 2009-01-20 17:16:47

0

为什么不只是坚持一个

 
if (_running == false) Start(); 

在Read()方法。 并且保护启动互斥或将其定义为“关键”以确保其单线程。

+0

我不想在每次Read()被调用时运行......很多时候,在调用Read()时什么都不应该发生。 – teeks99 2009-01-20 17:21:46