How to avoid polling in pthreads

I have code that currently looks like this (simplified)

/* instance in global var *mystruct, count initialized to 0 */ typedef struct { volatile unsigned int count; } mystruct_t; pthread_mutex_t mymutex; // is initialized /* one thread, goal: block while mystruct->count == 0 */ void x(void *n) { while(1) { pthread_mutex_lock(&mymutex); if(mystruct->count != 0) break; pthread_mutex_unlock(&mymutex); } pthread_mutex_unlock(&mymutex); printf("count no longer equals zero"); pthread_exit((void*) 0) } /* another thread */ void y(void *n) { sleep(10); pthread_mutex_lock(&mymutex); mystruct->count = 10; pthread_mutex_unlock(&mymutex); } 

This seems ineffective and wrong to me, but I don't know a better way to do this. Is there a better way, and if so, what is it?

+4
source share
5 answers

A common solution is to use the POSIX semaphore. They are not part of the pthread library, but they work with pthreads the same way.

Since semaphores are provided in most other multi-threaded APIs, this is a general method that can be applied, possibly more portable; however, perhaps a more suitable condition in this case is a condition variable , which allows the thread to depend on the conditional value of the variable without polling, which is apparently what you want.

+3
source

Variable conditions allow you to wait for a specific event and have a different signal stream that has a condition variable.

You may have a thread that does this:

 for (;;) { if (avail() > 0) do_work(); else pthread_cond_wait(); } 

and another thread that does this:

 for (;;) { put_work(); pthread_cond_signal(); } 

Very simplified, of course. :) You will need to see how to use it correctly, there are some difficulties with working with state variables due to race conditions.

However, if you are sure that the flow will block for a very short time (in the order of ΞΌs) and rarely, using such a spin cycle is likely to be more efficient.

+4
source

The condition of variables is the solution to this problem. Your code can be changed quite easily to use them:

 pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t mycond = PTHREAD_COND_INITIALIZER; /* one thread, goal: block while mystruct->count == 0 */ void x(void *n) { pthread_mutex_lock(&mymutex); while (mystruct->count == 0) pthread_cond_wait(&mycond, &mymutex); printf("count no longer equals zero"); pthread_mutex_unlock(&mymutex); pthread_exit((void*) 0) } /* another thread */ void y(void *n) { sleep(10); pthread_mutex_lock(&mymutex); mystruct->count = 10; pthread_cond_signal(&mycond); pthread_mutex_unlock(&mymutex); } 

Please note that you must keep the mutex locked during the result of the action - to β€œdestroy” the event or the like. So I moved pthread_mutex_unlock() to the point after printf() , although in this case the game does not matter.

(In addition, in the real code, the value of the mutex and the conditions inside the mystruct may well be marked).

+2
source

You can use barriers .

+1
source

You can also use semaphores to synchronize threads.

0
source

All Articles