我使用生产者-消费者模型用pthread编写了一个多线程程序。

当我使用英特尔VTune探查器对程序进行探查时,我发现生产者和使用者在pthread_mutex_unlock上花费了大量时间。我不明白为什么会这样。我认为线程可能需要等待很长时间才能获得互斥体,但是释放互斥体应该很快,对吗?

下面的快照来自Intel VTune。它显示了消费者尝试从缓冲区中获取项目的代码,以及每个代码行所消耗的时间。

我的问题是,为什么pthread_mutex_unlock有这么大的开销?是pthread互斥本身本身还是我的使用方式问题?

最佳答案

pthread_mutex_unlock()函数应释放互斥对象引用的互斥对象。但是,释放互斥锁的方式取决于互斥锁的type属性。如果在调用pthread_mutex_unlock()时互斥对象引用的互斥对象上有阻塞的线程,导致该互斥变得可用,则调度策略将确定哪个线程将获取该互斥。

如果互斥锁类型为PTHREAD_MUTEX_NORMAL,则不提供死锁检测。尝试重新锁定互斥锁会导致死锁。如果线程尝试解锁尚未锁定的互斥锁或已解锁的互斥锁,则会导致未定义的行为。

如果互斥类型为PTHREAD_MUTEX_ERRORCHECK,则应提供错误检查。如果线程试图重新锁定已经锁定的互斥锁,则将返回错误。如果线程试图解锁尚未锁定的互斥锁或已解锁的互斥锁,则将返回错误。

如果互斥锁类型为PTHREAD_MUTEX_RECURSIVE,则互斥锁应保持锁计数的概念。当线程首次成功获取互斥量时,锁定计数应设置为1。每当线程重新锁定此互斥锁时,锁定计数应增加一。每当线程解锁互斥锁时,锁计数应减一。当锁计数达到零时,互斥锁将可供其他线程获取。如果线程试图解锁尚未锁定的互斥锁或已解锁的互斥锁,则将返回错误。

如果互斥锁类型为PTHREAD_MUTEX_DEFAULT,则尝试递归锁定互斥锁将导致未定义的行为。如果未由调用线程锁定互斥锁,则尝试对其进行解锁会导致未定义的行为。如果未锁定互斥锁,则尝试对其进行解锁会导致未定义的行为。

我通常更喜欢使用PTHREAD_MUTEX_RECURSIVE互斥锁,因为在这种情况下,当计数达到零且调用线程对该互斥锁不再具有任何锁定时,该互斥锁将变为可用。

10-08 02:11