代码改变世界

Condition Variables(条件变量)用法指南

2010-12-30 12:01  zhenjing  阅读(3045)  评论(0编辑  收藏  举报

      int pthread_cond_timedwait(pthread_cond_t *restrict cond,

              pthread_mutex_t *restrict mutex,const struct timespec *restrict abstime);

      int pthread_cond_wait(pthread_cond_t *restrict cond,

              pthread_mutex_t *restrict mutex);

The pthread_cond_timedwait() and pthread_cond_wait() functions shall block on a condition variable. They shall be called with mutex locked by the calling thread or undefined behavior results.

These functions atomically release mutex and cause the calling thread to block on the condition variable cond; Upon successful return, the mutex shall have been locked and shall be owned by the calling thread. (State change: lock=> unlock and block => unblock and lock)

NOTE(condition variable and mutex): The effect of using more than one mutex for concurrent pthread_cond_timedwait() or  pthread_cond_wait() operations on the same condition variable is undefined.

Condition variable and thread cancellation

 A condition wait (whether timed or not) is a cancellation point. When the cancelability enable state of a thread is set to PTHREAD_CANCEL_DEFERRED, a side effect of acting upon a cancellation request while in a condition wait is that the mutex is (in effect) re-acquired before calling the first cancellation cleanup handler.

NOTE: if the mutex should be unlocked after thread cancellation, then the first cancellation cleanup handler is used to unlock mutex generally!

A  cancelled thread, which has  been  unblocked because  it  has been  canceled  while blocked  in  a  call  to pthread_cond_timedwait()  or  pthread_cond_wait(),  shall  not consume any condition signal.

Condition variable and signal

If a signal is delivered to a thread waiting for a condition variable, upon return from the signal handler the thread resumes waiting for the condition variableas if it was not interrupted, or it shall return zero due to spurious wakeup.

NOTE: It means that signal won’t block cond variable state!

Genaral Uasge

In general, whenever a condition wait returns, the thread has to re-evaluate the predicate associated with the condition waiting to determine whether it can safely proceed. A return from the wait does not imply that the associated predicate is either true or false. It is thus recommended that acondition wait be enclosed in the equivalent of a "while loop" thatchecks the predicate.

 

       int pthread_cond_broadcast(pthread_cond_t*cond);

       int pthread_cond_signal(pthread_cond_t *cond);

The pthread_cond_broadcast() function shall unblock all threads currently blocked on the specified condition variable cond.

The pthread_cond_signal() function shall unblock at least one of the threads that  are  blocked on  the specified condition variable cond

NOTE(waitup and mutex):The pthread_cond_broadcast() or pthread_cond_signal() functions may be called by a thread whether or not it  currently  owns the mutex that threads calling pthread_cond_wait() or pthread_cond_timedwait() have associated with the condition variable during their waits; however, if predictable  scheduling behavior is  required,  then that  mutex  shall be  locked  by the  thread calling pthread_cond_broadcast() or pthread_cond_signal().(The condition variable will be unblock but wait for mutex.)

The pthread_cond_broadcast() and pthread_cond_signal() functions shall have no effect if there  are no threads currently blocked on cond.(It means multi calls is safe!)

Condition variable and signal handler

It is not safe to use the pthread_cond_signal() function in a signal  handler that  is  invoked asynchronously.(It means pthread_cond_signal() shouldn’t be called in signal handler!)

Mutexes and condition variables are thus not suitable for releasing a waiting thread by signaling from code running in a signal handler.(Mutex and cond shouldn’t be used together with signal handler! IT IS NOT SAFE!)

Example:

            typedef struct {
                  pthread_mutex_t lock;
                  pthread_cond_t rcond,
                      wcond;
                  int lock_count; /* < 0 .. Held by writer. */
                                  /* > 0 .. Held by lock_count readers. */
                                  /* = 0 .. Held by nobody. */
                  int waiting_writers; /* Count of waiting writers. */
              } rwlock;

              void
              waiting_reader_cleanup(void *arg)
              {
                  rwlock *l;

                  l = (rwlock *) arg;
                  pthread_mutex_unlock(&l->lock);
              }

              void
              lock_for_read(rwlock *l)
              {
                  pthread_mutex_lock(&l->lock);
                  pthread_cleanup_push(waiting_reader_cleanup, l); //unlock after cancel
                  while ((l->lock_count < 0) && (l->waiting_writers != 0)) // while-loop
                      pthread_cond_wait(&l->rcond, &l->lock);
                  l->lock_count++;
                 /*
                  * Note the pthread_cleanup_pop executes
                  * waiting_reader_cleanup.
                  */
                  pthread_cleanup_pop(1);
              }

              void
              release_read_lock(rwlock *l)
              {
                  pthread_mutex_lock(&l->lock);
                  if (--l->lock_count == 0)
                      pthread_cond_signal(&l->wcond);
                  pthread_mutex_unlock(l);
              }

              void
              waiting_writer_cleanup(void *arg)
              {
                  rwlock *l;

                  l = (rwlock *) arg;
                  if ((--l->waiting_writers == 0) && (l->lock_count >= 0)) {
                     /*
                      * This only happens if we have been canceled.
                      */
                      pthread_cond_broadcast(&l->wcond);
              }
                  pthread_mutex_unlock(&l->lock);
              }

              void
              lock_for_write(rwlock *l)
              {
                  pthread_mutex_lock(&l->lock);
                  l->waiting_writers++;
                  pthread_cleanup_push(waiting_writer_cleanup, l);
                  while (l->lock_count != 0)
                      pthread_cond_wait(&l->wcond, &l->lock);
                  l->lock_count = -1;
                 /*
                  * Note the pthread_cleanup_pop executes
                  * waiting_writer_cleanup.
                  */
                  pthread_cleanup_pop(1);
              }

              void
              release_write_lock(rwlock *l)
              {
                  pthread_mutex_lock(&l->lock);
                  l->lock_count = 0;
                  if (l->waiting_writers == 0)
                      pthread_cond_broadcast(&l->rcond)
                  else
                      pthread_cond_signal(&l->wcond);
                  pthread_mutex_unlock(&l->lock);
              }

              /*
               * This function is called to initialize the read/write lock.
               */
              void
              initialize_rwlock(rwlock *l)
              {
                  pthread_mutex_init(&l->lock, pthread_mutexattr_default);
                  pthread_cond_init(&l->wcond, pthread_condattr_default);
                  pthread_cond_init(&l->rcond, pthread_condattr_default);
                  l->lock_count = 0;
                  l->waiting_writers = 0;
              }

              reader_thread()
              {
                  lock_for_read(&lock);
                  pthread_cleanup_push(release_read_lock, &lock);
                 /*
                  * Thread has read lock.
                  */
                  pthread_cleanup_pop(1);
              }

              writer_thread()
              {
                  lock_for_write(&lock);
                  pthread_cleanup_push(release_write_lock, &lock);
                 /*
                  * Thread has write lock.
                  */     
              pthread_cleanup_pop(1);
              }

---------------------------------------------------

兄弟的公司:立即购--手机购物,诚信网购

兄弟的公司:立即团

欢迎转载,请注明作者和出处