3

I am trying to implement a concurrent queue, and skeleton of implementation is as following:

struct queue
{
    int try_pop()
    {
        pthread_mutex_lock(&mutex_);
        int rt;
        while( (rt = do_pop()) == -1)
        {
            pthread_cond_wait(&cond_,&mutex_);
        }
        pthread_mutex_unlock(&mutex_);
        return rt;
    }

    bool push(int num)
    {
        pthread_mutex_lock(&mutex_);
        push_impl(num);
#if 0 
        /*signal before unlock*/
        pthread_cond_signal(&cond_);
        pthread_mutex_unlock(&mutex_);
#else
        /*signal after unlock*/
        pthread_mutex_unlock(&mutex_);
        pthread_cond_signal(&cond_);
#endif
        return true;
    }

    // private function and data member
}

I can call pthread_cond_signal before or after unlocking the mutex.

My question is what is difference between net effect of two approaches?

g-217
  • 2,069
  • 18
  • 33
  • 1
    There is a whole paragraph in the man page about this: https://linux.die.net/man/3/pthread_cond_signal – mch Feb 20 '17 at 08:57
  • This may be relevant: http://stackoverflow.com/questions/4544234/calling-pthread-cond-signal-without-locking-mutex/4544494, but OTOH, you do hold the mutex when changing the shared state, so maybe it is OK to unlock mutex before _signal in your case. – Erik Alapää Feb 20 '17 at 09:33

2 Answers2

1

It seems you are allowed to release mutex before doing _signal. On some systems, this may even reduce unnecessary context switching.

See http://www.domaigne.com/blog/computing/condvars-signal-with-mutex-locked-or-not/

Erik Alapää
  • 2,585
  • 1
  • 14
  • 25
1

If you have threads of different priorities contending on try_pop(), then signalling after unlocking leaves a window where a high-priority thread is blocked in pthread_cond_wait(), but a low-priority thread enters try_pop() in between the unlock and the signal, allowing it to jump in front of the high-priority thread. Signalling before unlocking will prevent this.

If you don't have different thread priorities contending like that, then signalling after unlocking will allow the signalled thread to wake up and immediately take the mutex, rather than having to move from "waiting on the condition variable" to an intermediate "waiting on the mutex" state first.

Really though, there is very little in it. It is unlikely to make any measurable difference.

caf
  • 233,326
  • 40
  • 323
  • 462