Reputation: 1698
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
Upvotes: 1
Views: 2065
Reputation: 6776
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 signal condxx
(like on a multiprocessor system), the kernel will have one of those calls to pthread_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 (your usleep()
idea).
That being said, there are some critical pieces of your code missing in your example. The mutexx
needs to be locked before calling pthread_cond_wait()
, and it must be locked and unlocked around the calls to pthread_cond_signal()
. This web page has an example that is very similar to your use case, and demonstrates proper locking techniques.
Upvotes: 3