我使用生产者 - 消费者模型用pthread编写了一个多线程程序。
当我使用英特尔VTune分析器来分析我的程序时,我发现生产者和消费者在pthread_mutex_unlock上花了很多时间。我不明白为什么会这样。我认为线程可能需要等待很长时间才能获得互斥锁,但释放互斥锁应该很快,对吗?
以下快照来自英特尔VTune。它显示了消费者尝试从缓冲区中获取项目的代码,以及每个代码行消耗的时间。
我的问题是为什么pthread_mutex_unlock有这样的开销?是pthread互斥体本身的问题还是我使用它的方式?
答案 0 :(得分:2)
pthread_mutex_unlock()函数将释放互斥锁引用的互斥锁对象。但是,释放互斥锁的方式取决于互斥锁的类型属性。如果在调用pthread_mutex_unlock()时互斥引用的互斥对象上存在线程阻塞,导致互斥锁变为可用,则调度策略将确定哪个线程将获取互斥锁。
如果互斥锁类型为PTHREAD_MUTEX_NORMAL,则不应提供死锁检测。尝试重新锁定互斥锁会导致死锁。如果某个线程尝试解锁未锁定的互斥锁或解锁的互斥锁,则会导致未定义的行为。
如果互斥锁类型为PTHREAD_MUTEX_ERRORCHECK,则应提供错误检查。如果某个线程试图重新锁定它已锁定的互斥锁,则应返回错误。如果某个线程尝试解锁未锁定的互斥锁或解锁的互斥锁,则应返回错误。
如果互斥锁类型为PTHREAD_MUTEX_RECURSIVE,则互斥锁应保持锁定计数的概念。当线程第一次成功获取互斥锁时,锁定计数应设置为1。每次线程重新锁定此互斥锁时,锁定计数应递增1。每次线程解锁互斥锁时,锁定计数应减1。当锁定计数达到零时,互斥锁将可供其他线程获取。如果某个线程尝试解锁未锁定的互斥锁或解锁的互斥锁,则应返回错误。
如果互斥锁类型为PTHREAD_MUTEX_DEFAULT,则尝试递归锁定互斥锁会导致未定义的行为。如果未通过调用线程锁定互斥锁,则尝试解锁互斥锁会导致未定义的行为。如果未锁定互斥锁,则尝试解锁互斥锁会导致未定义的行为。
我通常更喜欢使用PTHREAD_MUTEX_RECURSIVE互斥锁,因为在这种情况下,当计数达到零并且调用线程不再对此互斥锁有任何锁定时,互斥锁将变为可用。