15

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

当我使用英特尔 VTune 分析器分析我的程序时,我发现生产者和消费者在 pthread_mutex_unlock 上花费了大量时间。我不明白为什么会这样。我认为线程可能会等待很长时间才能获得互斥锁,但释放互斥锁应该很快,对吧?

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

我的问题是为什么 pthread_mutex_unlock 有这样的开销?是 pthread mutex 本身的问题还是我使用它的方式有问题? 在此处输入图像描述

4

1 回答 1

3

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

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

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

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

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

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

于 2013-07-15T15:08:22.263 回答