【问题标题】:Windows Event implementation in Linux using conditional variables?使用条件变量在 Linux 中实现 Windows 事件?
【发布时间】:2012-10-13 09:11:54
【问题描述】:

我正在尝试在 Linux 中实现非常简单的 Windows 事件。仅适用于我的场景 - 3 个线程,1 个主线程和 2 个辅助线程。每个辅助线程通过 SetEvent 引发 1 个事件,主线程等待它。示例:

int main()
{
    void* Events[2];
    Events[0] = CreateEvent();
    Events[1] = CreateEvent();

    pthread_start(Thread, Events[0]);
    pthread_start(Thread, Events[1]);

    WaitForMultipleObjects(2, Events, 30000) // 30 seconds timeout

    return 0;
}

int* thread(void* Event)
{
    // Do something
    SetEvent(Event);
    // Do something
}

所以,为了实现它,我使用条件变量。但我的问题是 - 这是正确的方法吗?还是我做错了什么?我的实现:

// Actually, this function return pointer to struct with mutex and cond
// here i just simplified example
void* CreateEvent(mutex, condition)
{
    pthread_mutex_init(mutex, NULL);
    pthread_cond_init(condition, NULL);
}

bool SetEvent (mutex, condition)
{
    pthread_mutex_lock(mutex);
    pthread_cond_signal(condition);
    pthread_mutex_unlock(mutex);
}

int WaitForSingleObject(mutex, condition, timeout)
{
    pthread_mutex_lock(mutex);
    pthread_cond_timedwait(condition, mutex, timeout);
    pthread_mutex_unlock(mutex);
}

// Call WaitForSingleObject for each event. 
// Yes, i know, that its a wrong way, but it should work in my example.
int WaitForMultipleObjects(count, mutex[], condition[], timeout);

一切似乎都很好,但我认为,当我在主线程中调用 WaitFor.. 函数时,会出现该问题,然后调用辅助线程中的 SetEvent。在 Windows 中,它运行良好,但在 Linux 中 - 上面仅描述了想法。

也许你能告诉我更好的解决方法?谢谢。

UPD:超时非常重要,因为其中一个辅助线程可能不会通过 SetEvent()。

【问题讨论】:

标签: c++ linux multithreading synchronization mutex


【解决方案1】:

stackoverflow 上已经有类似问题:WaitForSingleObject and WaitForMultipleObjects equivalent in linux

另外你可以使用信号量:

sem_t semOne  ;
sem_t semTwo  ;
sem_t semMain ;

在主线程中:

sem_init(semOne,0,0) ;
sem_init(semTwo,0,0) ;
sem_init(semMain,0,0) ;

...


sem_wait(&semMain);

// Thread 1
sem_wait(&semOne);
sem_post(&semMain);


// Thread 2
sem_wait(&semTwo);
sem_post(&semMain);

详细描述和各种示例可以在这里找到:------http://www.ibm.com/developerworks/linux/library/l-ipc2lin3/index.html

以前的链接不再可用。 The Internet Archive's Wayback Machine 的最新存档版本是: https://web.archive.org/web/20130515223326/http://www.ibm.com/developerworks/linux/library/l-ipc2lin3/index.html

【讨论】:

  • 谢谢,但是超时怎么办?据我所知,信号量没有它。
  • 你可以简单地使用 sem_timedwait() 而不是 sem_wait()。
  • 我认为,信号量不能定时等待...谢谢)
  • 他们为什么等不及了?有一些关于 sem_timewait() 的错误。你可以在herehere找到一些线索。
【解决方案2】:

我认为信号量在这里是一个更好的解决方案,因为它可以在进程间使用。 可以封装接口,如果没有提供name,则使用pthread_初始化,供进程内使用,这样可以缩短资源使用量,但是使用name时,尽量使用sem初始化,供进程内使用。

【讨论】:

    【解决方案3】:

    基于WaitForSingleObject的描述

    WaitForSingleObject 函数检查指定对象的当前状态。如果对象的状态是非信号状态,则调用线程进入等待状态,直到对象被信号或超时间隔过去。

    该行为与代码之间的区别在于代码将始终等待条件变量,因为它不检查谓词。这会在 pthread_condt_timewaitpthread_cond_signal 调用之间引入同步问题。

    发出条件变量信号的一般习惯用法是:

    锁定互斥体
    设置谓词
    解锁互斥锁
    信号条件变量
    

    而在等待条件变量时:

    锁定互斥体
    而(!谓词)
    {
      等待条件变量
    }
    解锁互斥锁

    根据要完成的工作,可以将单独的bool 用作每个Event 的谓词。通过引入谓词,WaitForSingleObject 应该只在Event 未发出信号时等待条件变量。代码将类似于以下内容:

    bool SetEvent (mutex, condition)
    {
        pthread_mutex_lock(mutex);                 // lock mutex
        bool& signalled = find_signal(condition);  // find predicate
        signalled = true;                          // set predicate
        pthread_mutex_unlock(mutex);               // unlock mutex
        pthread_cond_signal(condition);            // signal condition variable
    }
    
    int WaitForSingleObject(mutex, condition, timeout)
    {
        pthread_mutex_lock(mutex);                         // lock mutex
        bool& signalled = find_signal(condition);          // find predicate
        while (!signalled)
        {
          pthread_cond_timedwait(condition, mutex, timeout);
        }
        signalled = false;                                 // reset predicate
        pthread_mutex_unlock(mutex);                       // unlock mutex
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-05-13
      • 2012-06-15
      • 2011-07-18
      • 2010-10-30
      • 2020-09-07
      • 1970-01-01
      • 2011-08-15
      相关资源
      最近更新 更多