My environment is in Linux, using pthreads, compiled in gcc.
I have 3 threads as socket threads which receive socket data,
about 1500 rows per second for thread1 and thread2,
thread3 will receive 400 rows per second,
in thread1, thread2, thread3, I use mutex_lock to protect global vars,
so that thread4 get these global vars would be correct, of course thread4 use
mutex_lock, too.
Thread1:
Pthread_mutex_lock(&Mutex1);
iGlobal1 = iGlobal1 + 1;
Pthread_mutex_unlock(&Mutex1);
Thread2:
Pthread_mutex_lock(&Mutex2);
iGlobal2 = iGlobal2 + 1;
Pthread_mutex_unlock(&Mutex2);
Thread3:
Pthread_mutex_lock(&Mutex3);
iGlobal3 = iGlobal3 + 1;
Pthread_mutex_unlock(&Mutex3);
Thread4:
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
In my opinion Thread4 can be more efficient, because if thread4 execute too frequently,
it costs a lot of cpu, and mutex_lock effect thread1, thread2 and thread3…
so I think using pthread_cond_signal will make it better, like following:
Thread1:
Pthread_mutex_lock(&Mutex1);
iGlobal1 = iGlobal1 + 1 ;
pthread_cond_signal(&condxx);
Pthread_mutex_unlock(&Mutex1);
Thread2:
Pthread_mutex_lock(&Mutex2);
iGlobal2 = iGlobal2 + 1 ;
pthread_cond_signal(&condxx);
Pthread_mutex_unlock(&Mutex2);
Thread3:
Pthread_mutex_lock(&Mutex3);
iGlobal3 = iGlobal3 + 1 ;
pthread_cond_signal(&condxx);
Pthread_mutex_unlock(&Mutex3);
Thread4:
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
Because pthread_cond_signal won’t queue signal, so it has no harm in
thread1, thread2, thread3 to fire pthread_cond_signal each time receive socket data,
and thread4 will be blocked in pthread_cond_wait(&condxx, mutexx) until get
pthread_cond_signal, that will save cpu time and also won’t effect thread1, thread2, thread3 because less mutex_lock used!
My idea is, using pthread_cond_wait acting like usleep,
but while data arrived, thread4 won’t miss!
May I ask, What I do has any side effect? Any advice is welcome
I think your approach to making thread 4 more efficient is a good one. If there were only thread 1 (the producer) and thread 4 (the consumer), your approach is the standard way to have thread 4 efficiently wait for data to be made available by thread 1. The wrinkle here is the presence of multiple producer threads (threads 2 and 3).
The man page for
pthread_cond_signal()says that signaling a condition on which no thread is waiting shall have no effect, so in the case where threads 1, 2, and 3 simultaneously signalcondxx(like on a multiprocessor system), the kernel will have one of those calls topthread_cond_signal()actually unblock thread 4, while the other two will have no effect.In other words, I think your approach will work. And it is always better to have waiting for data managed by the kernel (
pthread_cond_wait(),select(), etc.) than to poll for it in a loop (yourusleep()idea).That being said, there are some critical pieces of your code missing in your example. The
mutexxneeds to be locked before callingpthread_cond_wait(), and it must be locked and unlocked around the calls topthread_cond_signal(). This web page has an example that is very similar to your use case, and demonstrates proper locking techniques.