barfatchen
barfatchen

Reputation: 1698

A implement of pthread_cond_wait and pthread_cond_signal , any side-effect?

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

Answers (1)

Randall Cook
Randall Cook

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

Related Questions