Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use a mutex as a semaphore?

I need two threads to progress in a "tick tock" pattern. When implmented with a semaphore this looks fine:

Semaphore tick_sem(1);
Semaphore tock_sem(0);

void ticker( void )
{
   while( true )
   {
      P( tick_sem );
      do_tick();
      V( tock_sem );
   }
}

void tocker( void )
{
   while( true )
   {
      P( tock_sem );
      do_tock();
      V( tick_sem );
   }
}

However, if I do the same thing with a mutex ( which is technically a binary semaphore ), it has an odd code smell.

std::mutex tick_mutex;
std::mutex tock_mutex;
tock_mutex.lock();

void ticker( void )
{
   while( true )
   {
      tick_mutex.lock();
      do_tick();
      tock_mutex.unlock();
   }
}

void tocker( void )
{
   while( true )
   {
      tock_mutex.lock()
      do_tock();
      tick_mutex.unlock();
   }
}

I think the smell is that a mutex isn't meant to convey information to another thread. (The c++11 standard committee added a spurious fail to try_lock to defeat unexpected information transfer; §30.4.1/14.) It seems like mutexes are meant to synchronize access to a variable, which can then convey information to another thread.

Lastly, when implemented with a std::condition_variable, it looks correct but it's more complicated ( a tick_vs_tock variable, a mutex, and a condition variable). I've omitted the implementation for brevity, but it's really straight forward.

Is the mutex solution fine? Or is there something subtly wrong with it?

Is there a good pattern for solving my tick/tock problem that I haven't thought of?

like image 558
deft_code Avatar asked Jul 23 '11 23:07

deft_code


People also ask

Can we use semaphore as mutex?

Myth: Mutexes and Semaphores are Interchangeable The most common (but nonetheless incorrect) answer to the question posed at the top is that mutexes and semaphores are very similar, with the only significant difference being that semaphores can count higher than one.

Which is better semaphore or mutex?

If you have number of instances for resource it is better to use Binary semaphore. If you have single instance for resource it is better to use mutex.

In what scenarios mutex is used and semaphore is used?

The mutex is used for protecting parts of code from running concurrently, semaphores are used for one thread to signal another thread to run.

Can mutex be used across process?

Mutexes can synchronize threads within the same process or in other processes. Mutexes can be used to synchronize threads between processes if the mutexes are allocated in writable memory and shared among the cooperating processes (see mmap(2)), and have been initialized for this task.


2 Answers

A Mutex is not simply just a binary semaphore, it also has the limitation that only the locking thread is allowed to unlock it.

You are breaking that rule.

Edit:

From MSDN:

The ReleaseMutex function fails if the calling thread does not own the mutex object.

From some site that google turned up for pthread_mutex_unlock:

The pthread_mutex_unlock() function may fail if:

EPERM The current thread does not own the mutex.

And you will find the same on other mutex implementations. It makes sense because a mutex is supposed to guard a thread's access to a resource, so another thread should not be able to unlock it.

like image 199
Fozi Avatar answered Sep 27 '22 22:09

Fozi


Since you have a case to use a semaphore, I think the fix is to portably implement one using a mutex and a condition variable.

This might not be especially efficient (since it'll use a mutex/condvar pair per semaphore), but you can switch in an alternate implementation on systems that have their own semaphores (such as Posix and Windows).

Apparently semaphores are "too error-prone". With all due respect to Boost, I think at least some of us can manage. Certainly you can tie yourself in knots trying to do complicated things with multiple semaphores, and they are a pretty low-level tool. But when they're the right thing, no problem.

like image 24
Steve Jessop Avatar answered Sep 27 '22 21:09

Steve Jessop