Qt QSemaphore的发布()没有立即通知服务员?

时间:2011-11-03 23:39:13

标签: qt mutex semaphore

我已经编写了一个Qt控制台应用程序来试用QSemaphores,并发现了一些奇怪的行为。考虑具有1个资源和两个线程获取和释放单个资源的信号量。伪代码:

QSemaphore sem(1);   // init with 1 resource available

thread1()
{
    while(1)
    {
        if ( !sem.tryAquire(1 resource, 1 second timeout) )
        {
            print "thread1 couldn't get a resource";
        }
        else
        {
            sem.release(1);
        }
    }
}

// basically the same thing
thread2()
{
    while(1)
    {
        if ( !sem.tryAquire(1 resource, 1 second timeout) )
        {
            print "thread2 couldn't get a resource";
        }
        else
        {
            sem.release(1);
        }
    }
}

似乎很简单,但线程通常无法获得资源。解决这个问题的一种方法是让线程在sem.release(1)之后暂停一段时间。这告诉我的是release()成员在当前线程循环到tryAquire()的顶部并且再次抓取资源之前不允许其他线程在while(1)中等待访问信号量。

这让我感到惊讶,因为使用QMutex的类似测试显示了正确的行为...即QMutex::tryLock(timeout)中挂出的另一个帖子在调用QMutex::unlock()时会得到正确的通知。

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

我目前无法完全测试或找到所有支持链接,但这里有一些观察......

首先,documentation for QSemaphore.tryAcquire表示超时值是毫秒,而不是秒。因此,您的线程只等待1毫秒才能使资源变为空闲。

其次,我记得在某个地方(遗憾的是我不记得在哪里)阅读有关当多个线程试图同时获取相同资源时会发生什么的讨论。虽然行为可能因操作系统和情况而异,但似乎典型的结果是它是一个免费的,没有任何一个线程被赋予比另一个更优先。因此,等待获取资源的线程获得它的机会与刚刚释放它的线程一样多,并且尝试立即重新获取它。我不确定线程​​的priority setting是否会影响这个。

那么,为什么QSemaphore与QMutex会有不同的结果?好吧,我认为信号量可能是一个更复杂的系统资源,需要更多的时间来获取和释放互斥锁。我最近为互斥体做了一些简单的计时,并发现平均需要大约15-25微秒来锁定或解锁一个。在你的线程等待的1毫秒内,这将是至少20个锁定和解锁周期,并且同一线程总是在该时间内重新获得锁定的几率很小。等待线程可能会在等待的时间内至少在苹果上咬一口,因此在您的示例中使用互斥锁时,您不会看到任何采集失败。

然而,如果释放和获取信号量需要更长时间(我没有计时,但我猜他们可能),那么你很可能只是偶然得到一个线程能够继续重新获取资源,直到等待线程的等待条件用完为止。