sokiiya 发表于 2008-11-21 13:23:07

问个问题,有关线程的挂起

想和大家交流下:
一个线程把自己挂起,然后等满足一些条件再由别的线程把它唤醒。
这些一般使用ace的什么呢?
我用了ACE_Condition<ACE_Thread_Mutex>:
创建了一对ACE_Thread_Mutex和ACE_Condition,挂起的时候先锁住、在调wait;唤醒的时候也锁、然后signal:
挂起:
st.pMutex->acquire();
st.pCondition->wait();
st.pMutex->release();
唤醒:
st.pMutex->acquire();
st.pCondition->signal();
st.pMutex->release();

可是很偶尔提示唤醒成功了,但是被挂起线程仍然没有继续向下走。不知这会是什么原因。


ACE_Thread_Manager::instance()->suspend(thid);用这个不能把自己挂起,resume的时候唤不醒,这只能用于挂起别的线程。

winston 发表于 2008-11-21 22:44:44

个人之见,还是OS决定的线程调度,ACE只是调用了API。所以,我觉得应该是正常的。

wishel 发表于 2008-11-22 09:21:21

楼主代码,signal的时候永远不会有线程在wait,反之亦然

wishel 发表于 2008-11-23 00:24:25

sorry,上面说错了
wait实际上是一个原子操作,包括2个动作:
1,wait , block
2,释放该条件变量对应的mutex
在wait返回时,自动重新获得该mutex,如果不能获得是不会返回的

所以在唤醒的时候,一定要先release,再signal

sokiiya 发表于 2008-11-24 11:07:38

ace很多例子里面用mutex和condition都是用ACE_GUARD_RETURN,加上这个宏,其实就是锁住然后wait、锁住然后signal。

wishel 发表于 2008-11-24 20:00:02

汗。。。仔细看了下第一册书和APUE的内容,都只是提到wait返回后一定是重新获得了lock的,但是并没有说如果另一线程发signal或broadcast时如果并没有释放锁,会怎么样。
ACE的示例程序是用的guard,但是下面这种情况会怎么样呢?

挂起等待:
{
ACE_Guard<ACE_Thread_Mutex> guard(lock);
condition.wait();
}
通知唤醒:
{
ACE_Guard<ACE_Thread_Mutex> guard(lock);
condition.signal();
ACE_OS::sleep(2);
}

[ 本帖最后由 wishel 于 2008-11-24 20:10 编辑 ]

wishel 发表于 2008-11-24 20:06:19

我写了个测试程序测了下,两个线程分别是:
ACE_Thread_Mutex lock;
ACE_Condition_Thread_Mutex condition(lock);
DWORD waitCondition(void*) {
      ACE_Guard<ACE_Thread_Mutex> guard(lock);
      cout << "begin wait" << endl;
      condition.wait();
      cout << "wait over" << endl;
      return 0;
}
DWORD signalCondition(void*) {
      ACE_OS::sleep(2); // 保证wait先执行
      ACE_Guard<ACE_Thread_Mutex> guard(lock);
      cout << "begin signal" << endl;
      condition.signal();
      cout << "begin sleep" << endl;
      ACE_OS::sleep(2); // 模拟耗时较长的任务
      cout << "sleep over" << endl;
      return 0;
}

int ACE_TMAIN (int argc, ACE_TCHAR *argv[]) {
    ACE_Thread_Manager::instance()->spawn(waitCondition);
    signalCondition(0);
    ACE_Thread_Manager::instance()->wait();
    return 0;
}

结果:
begin wait
begin signal
begin sleep
sleep over
wait over

可以看到,只有signal线程运行结束,打印出sleep over后,wait线程的wait才获得lock并返回,虽然早就收到signal了

[ 本帖最后由 wishel 于 2008-11-24 20:08 编辑 ]

wishel 发表于 2008-11-24 20:07:32

楼主程序的问题可能是没控制2个线程的执行次序,signal线程先运行了,然后wait线程就没人唤醒了。
页: [1]
查看完整版本: 问个问题,有关线程的挂起