HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

std::lock implementation in C with pthreads

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
stdpthreadswithimplementationlock

Problem

I messed a little bit with pthreads and needed an alternative to the C++11 function std::lock (2 args are enough), and this is what I came up with:

void lock(pthread_mutex_t* m1, pthread_mutex_t* m2) {
  while(1) {
    pthread_mutex_lock(m1);

    if(pthread_mutex_trylock(m2) == 0) { // if lock succesfull
      break;
    }
    pthread_mutex_unlock(m1);
    sched_yield();
  }
}


It works fine so far. I am just not sure whether I missed some potential deadlock.

In addition, I am interested if I should do some more error checking. I am especially not that firm with C-style error checking.

Solution

It does not look like your code will deadlock.

That said, I am not very keen on the spin lock like attempt, as I can see situations where it may not be great in efficiency.

It (std::lock) guarantees that no matter what order you specify the locks in the parameter list you will not fall into a deadlock situation.

A common technique (simple enough you could use (but the standard does not specify whether this technique is used by std::lock)) is to make sure the locks are ordered in some way. This basically means that the order you lock the mutexes in must be consistent (thus independent of the order they are in the parameter list).

  • The actual order should be defined in terms of some immutable property of the underlying mutex (such as its address).



  • This also means that if a lock in the list is already locked it must be released so that the locks are acquired in the correct order (Note: not all lockables can safely call try_lock() so you can't always determine if you should unlock).



Example of deadlock occurring when locks are not acquired in order:

Time:     Thread-1          Thread-2
           lock(g2, g1)      lock(g1, g2)

   0       lock(&g2)
   
   1                         lock(&g1)

   2       lock(&g1) // Can never succeed
   
   3                         lock(&g2) // Can never succeed


Metal deadlock.

Thread 1 is now waiting for g1 (held by thread 2), while thread 2 is waiting for g2 (held by thread 1).

Code Snippets

Time:     Thread-1          Thread-2
           lock(g2, g1)      lock(g1, g2)


   0       lock(&g2)
   
   1                         lock(&g1)

   2       lock(&g1) // Can never succeed
   
   3                         lock(&g2) // Can never succeed

Context

StackExchange Code Review Q#11935, answer score: 7

Revisions (0)

No revisions yet.