【发布时间】:2012-01-11 07:01:14
【问题描述】:
我的环境是Linux,使用pthreads,用gcc编译。
我有 3 个线程作为接收套接字数据的套接字线程, thread1 和 thread2 每秒大约 1500 行, thread3 每秒将接收 400 行, 在thread1、thread2、thread3中,我使用mutex_lock来保护全局变量, 这样thread4获取这些全局变量是正确的,当然thread4使用 mutex_lock 也是如此。
线程1:
Pthread_mutex_lock(&Mutex1);
iGlobal1 = iGlobal1 + 1;
Pthread_mutex_unlock(&Mutex1);
线程2:
Pthread_mutex_lock(&Mutex2);
iGlobal2 = iGlobal2 + 1;
Pthread_mutex_unlock(&Mutex2);
线程3:
Pthread_mutex_lock(&Mutex3);
iGlobal3 = iGlobal3 + 1;
Pthread_mutex_unlock(&Mutex3);
线程4:
while(1)
{
Pthread_mutex_lock(&Mutex1);
ilocal1 = iGlobal1;
Pthread_mutex_unlock(&Mutex1);
Pthread_mutex_lock(&Mutex2);
ilocal2 = iGlobal2;
Pthread_mutex_unlock(&Mutex2);
Pthread_mutex_lock(&Mutex3);
ilocal3 = iGlobal3;
Pthread_mutex_unlock(&Mutex3);
DoSomething(ilocal1,ilocal2,ilocal3);
}//while
在我看来Thread4可以更高效,因为如果thread4执行太频繁, 它消耗大量cpu,并且mutex_lock影响thread1,thread2和thread3...... 所以我认为使用 pthread_cond_signal 会更好,如下所示:
线程1:
Pthread_mutex_lock(&Mutex1);
iGlobal1 = iGlobal1 + 1 ;
pthread_cond_signal(&condxx);
Pthread_mutex_unlock(&Mutex1);
线程2:
Pthread_mutex_lock(&Mutex2);
iGlobal2 = iGlobal2 + 1 ;
pthread_cond_signal(&condxx);
Pthread_mutex_unlock(&Mutex2);
线程3:
Pthread_mutex_lock(&Mutex3);
iGlobal3 = iGlobal3 + 1 ;
pthread_cond_signal(&condxx);
Pthread_mutex_unlock(&Mutex3);
线程4:
while(1)
{
pthread_cond_wait(&condxx, mutexx);
Pthread_mutex_lock(&Mutex1);
ilocal1 = iGlobal1;
Pthread_mutex_unlock(&Mutex1);
Pthread_mutex_lock(&Mutex2);
ilocal2 = iGlobal2;
Pthread_mutex_unlock(&Mutex2);
Pthread_mutex_lock(&Mutex3);
ilocal3 = iGlobal3;
Pthread_mutex_unlock(&Mutex3);
DoSomething(ilocal1,ilocal2,ilocal3);
}//while
因为 pthread_cond_signal 不会对信号进行排队,所以它在 thread1, thread2, thread3 每次接收套接字数据时触发 pthread_cond_signal, 并且 thread4 将被阻塞在 pthread_cond_wait(&condxx, mutexx) 直到 get pthread_cond_signal,这将节省 cpu 时间,并且不会影响 thread1、thread2、thread3,因为使用的 mutex_lock 更少!
我的想法是,使用 pthread_cond_wait 表现得像 usleep, 但是当数据到达时,thread4不会错过!
请问,我做的有什么副作用吗?欢迎任何建议
【问题讨论】:
-
thread4 中的 DoSomething() 是否要求所有 3 个线程都更改了各自的全局或仅更改一个? thread4 是否以任何方式更改全局变量?全局变量是否不仅仅是内置类型并且相对较小?换句话说,如果 DoSomething() 只是更新一个 GUI 计数器或一些类似的操作,您可能能够一起免除锁,而只需将线程 1、2、3 写入管道。线程 4 挂在读取的管道上并执行其操作。
-
谢谢你,Duck,一旦 Thread1,thread2,threa3 之一发生变化,它需要调用 DoSomething ,DoSomething 不会改变全局变量,但是 Dosomething 需要复杂的计算,完成的成本时间,我认为管道是个好主意,谢谢你的好建议!
-
转念一想,在 Dosomethin 执行过程中,同时 Thread1 收到了 3 个数据,thread2 收到了 5 个数据,thread3 收到了 1 个数据,我只喜欢只使用第 3 个数据thread1 的第 5 个数据,thread2 的第 5 个数据,thread3 中的第 1 个数据,一起填写 DoSomething ,在我的情况下使用管道不是一个好主意!