关于条件锁和互斥锁(pthread_cond_t和pthread_mutex_t)的疑问

Andy-老周 2009-07-30 09:53:26
这两天考虑互斥锁的原理,做了一些代码测试,反倒越来越迷惑了。


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

pthread_cond_t _cond;
pthread_mutex_t condmutex;

class Test
{
public:
static void func()
{
//pthread_mutex_t hSingletonMutex;
//pthread_mutex_init(&hSingletonMutex, NULL);

if (i == 0)
{
//pthread_mutex_lock(&hSingletonMutex);
i++;
}
//pthread_mutex_unlock(&hSingletonMutex);
//pthread_mutex_destroy(&hSingletonMutex);
}

static int getI()
{
return i;
}

protected:
Test() {}

virtual ~Test() {}

private:
static int i;

};

int Test::i = 0;

void threadfunc()
{
pthread_mutex_lock(&condmutex);
pthread_cond_wait(&_cond, &condmutex);

//printf("wait singal finished\n");
Test::func();

pthread_mutex_unlock(&condmutex);
}

void threadfunc2()
{
pthread_mutex_lock(&condmutex);
pthread_cond_broadcast(&_cond);
//pthread_cond_signal(&_cond);
pthread_mutex_unlock(&condmutex);
}

int main(int argc, char** argv)
{
pthread_mutex_init(&condmutex, NULL);
pthread_cond_init(&_cond, NULL);

unsigned int count = 10;
if (argc == 2)
{
count = atoi(argv[1]);
}

pthread_t t_id[count];
pthread_t thread;
int i = 0;


for (; i < count; i++)
{
pthread_create(&t_id[i], NULL, (void*(*)(void*))threadfunc, NULL);
}

printf("create %d thread finished\n", count);
pthread_create(&thread, NULL, (void*(*)(void*))threadfunc2, NULL);
printf("create another thread finished\n");


for (i = 0; i < count; i++)
{
pthread_join(t_id[i], NULL);
}

pthread_cond_destroy(&_cond);
pthread_mutex_destroy(&condmutex);

printf("i = %d\n", Test::getI());

return 0;
}


Test类模拟单例类,为了让多个线程并发,添加了条件锁,在func()不加锁的情况下,i一直等于1,说明多个线程没出现不同步的情况,但出现了一下问题:

1. 将条件锁加到main中时,即在进程中触发singal,此时线程中的wait依然阻塞,但在另一个单独的线程触发singal时,没有问题。难道这些锁只为线程准备的?

2. 用pthread_cond_signal(&_cond)时,只能触发一个线程不在等待,系统会调度哪个线程开始工作,其他线程依然wait阻塞,这个应该理解对了,所以用broadcast时才能出发所有线程。

3. 在static void func()这个静态函数中,初始化一个局部变量的锁,到底有没有作用?是不是非要弄成全局的或成员变量等形式,不能用局部变量呢?这个怎么也试不出来。

4. 模拟了半天,多个线程阻塞后,接到singal后,同时开始工作,也没有出现i的异常,不解,难道模拟线程同时工作有问题?



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/andy6355/archive/2009/07/29/4390521.aspx
...全文
1700 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
huacong20082009 2012-03-16
  • 打赏
  • 举报
回复
pthread_cond_t必须配一个互斥锁保护,要不会出现死锁。
decrement_count () {
pthread_mutex_lock (&count_lock);
while(count==0)
pthread_cond_wait( &count_nonzero, &count_lock);
count=count -1;
pthread_mutex_unlock (&count_lock);
}
increment_count(){
pthread_mutex_lock(&count_lock);
if(count==0)
pthread_cond_signal(&count_nonzero); //如果不用互斥锁,在此处出现线程切换将导致decrement_count一直阻塞
count=count+1;
pthread_mutex_unlock(&count_lock);
}
Andy-老周 2009-11-19
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 erwin1984 的回复:]
问题在于 threadfunc 和 threadfunc2 都用的 pthread_mutex_lock(&condmutex);

而threadfunc 需要 threadfunc2 中的pthread_cond_broadcast(&_cond);来触发,很明显导致死锁了,因为其中一个 threadfunc 已经占有了 condmutex, threadfunc2 没法进入condmutex。

_cond 应该需要另外一个mutex来保护才行的, 对i 的保护用一个mutex。

同时你的一些问题都是由于只有一个 threadfunc 进入了 pthread_mutex_lock(&condmutex); 在 pthread_cond_broadcast(&_cond) 等待,其余的都挂起在 pthread_mutex_lock(&condmutex);了, 即使broadcast也只触发了一个 threadfunc, 你可以用调试器看一下每一个线程的状态就明白了。



[/Quote]
我并不像保护i,就是想让i出错。同时并未发生死锁,condmutex就是配合条件变量使用的互斥锁,在这里是不会发生死锁的,我编译执行过了。我的问题是帖子的后面的那4个。
我也调试过,只要threadfunc2执行了,10个执行threadfunc的线程都被触发,可以开始执行
yutaooo 2009-11-19
  • 打赏
  • 举报
回复

LZ 先说一下测试环境。是多CPU,超线程,多核,还是单个早期CPU?
sun007700 2009-11-19
  • 打赏
  • 举报
回复
“4. 模拟了半天,多个线程阻塞后,接到singal后,同时开始工作,也没有出现i的异常,不解,难道模拟线程同时工作有问题? ”

没有问题的,因为你用的“pthread_mutex_lock(&condmutex);
pthread_cond_wait(&_cond, &condmutex);

//printf("wait singal finished\n");
Test::func();

pthread_mutex_unlock(&condmutex);

这个形式就表明了会对“Test::func();”加锁互斥了。
每个线程“wait”时,只有等到“unlock”释放了锁,才可以有抢锁的机会,如果没有抢到锁,则继续“wait”,再次等锁释放了,再继续抢锁,以此类推。
你可以用gdb调试跟下看看就明白了。
sun007700 2009-11-19
  • 打赏
  • 举报
回复
“1. 将条件锁加到main中时,即在进程中触发singal,此时线程中的wait依然阻塞,但在另一个单独的线程触发singal时,没有问题。难道这些锁只为线程准备的? ”

没有发现有这个问题啊,我把你的线程2里的“
pthread_mutex_lock(&condmutex);
pthread_cond_broadcast(&_cond);
//pthread_cond_signal(&_cond);
pthread_mutex_unlock(&condmutex);

替换掉了
“pthread_create(&thread, NULL, (void*(*)(void*))threadfunc2, NULL);

结果是一样的,没有出现wait不往下走的情况。
erwin1984 2009-07-31
  • 打赏
  • 举报
回复
问题在于 threadfunc 和 threadfunc2 都用的 pthread_mutex_lock(&condmutex);

而threadfunc 需要 threadfunc2 中的pthread_cond_broadcast(&_cond);来触发,很明显导致死锁了,因为其中一个 threadfunc 已经占有了 condmutex, threadfunc2 没法进入condmutex。

_cond 应该需要另外一个mutex来保护才行的, 对i 的保护用一个mutex。

同时你的一些问题都是由于只有一个 threadfunc 进入了 pthread_mutex_lock(&condmutex); 在 pthread_cond_broadcast(&_cond) 等待,其余的都挂起在 pthread_mutex_lock(&condmutex);了, 即使broadcast也只触发了一个 threadfunc, 你可以用调试器看一下每一个线程的状态就明白了。




Andy-老周 2009-07-31
  • 打赏
  • 举报
回复
请高人解答

64,682

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧