Question

Je développe une application sur un système d'exploitation Linux intégré (uclinux) et je dois pouvoir verrouiller le mutex plus d'une fois (par le même thread).

J'ai un mutex et un mutexattr défini et initialisé comme suit:

pthread_mutexattr_t waiting_barcode_mutexattr;
pthread_mutex_t waiting_barcode_mutex;

pthread_mutexattr_init(&waiting_barcode_mutexattr);
pthread_mutexattr_settype(&waiting_barcode_mutexattr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&waiting_barcode_mutex, &waiting_barcode_mutexattr);

Mais quand j'essaie d'acquérir le verrou deux fois, il bloque le deuxième serrure:

pthread_mutex_lock(&waiting_barcode_mutex);
pthread_mutex_lock(&waiting_barcode_mutex);

Est-ce que je l'initialise mal ou y a-t-il une meilleure façon de réaliser la même chose?

Merci d'avance.

Conclusions:

  • Apparemment, pthread_mutex_recursive ou pthread_mutex_recursive_np ne fonctionne pas donc je ne peux pas créer un mutex réentrant.
  • Try_lock n'est pas bon non plus. Il acquiert le verrou s'il le peut et renvoie une erreur s'il ne peut pas acquérir le verrou. Malheureusement, l'erreur m'informe simplement que le mutex est déjà utilisé et je ne peux pas savoir si le fil actuel est déjà propriétaire du verrou ou non.
  • pthread_mutex_lock peut renvoyer une erreur si le thread actuel a le verrouillage, mais pour cela, je dois créer un mutex du type pthread_mutex_errorcheck, et je ne peux pas en créer un non plus.
Était-ce utile?

La solution 5

(Just realised I didn't mark this question as answered)

Taken from the Conclusions in the question:

  • Apparently PTHREAD_MUTEX_RECURSIVE or PTHREAD_MUTEX_RECURSIVE_NP don't work so I can't create a reentrant mutex.
  • try_lock is no good either. It acquires the lock if it can and returns an error if it can't acquire the lock. Unfortunately the error just informs me that the mutex is already in use and I can´t find out if the current thread already owns the lock or not.
  • pthread_mutex_lock can return an error if the current thread has the lock but for that I need to create a mutex of the type PTHREAD_MUTEX_ERRORCHECK, and I can't create one either.

Autres conseils

Est-ce que cela ne fait pas ce à quoi vous vous attendriez?

Le premier appel acquiert le verrou et le second bloquera jusqu'à la sortie du premier verrou (pthread_mutex_unlock). C'est ce que font les verrous.

À partir de la documentation:

"Si le mutex est déjà verrouillé, le fil d'appel bloque jusqu'à ce que le mutex soit disponible."

Peut-être que tu veux pthread_mutex_trylock? Il est difficile de dire à moins que nous sachions ce que vous essayez d'accomplir.

CORRECTION:

Je n'ai pas vu que vous définissiez pthread_mutex_recursive .... Permettez-moi de réfléchir un peu plus.

Après avoir pensé:

De pivoter autour de Google Codesearch, il semble que pthread_mutex_recursive ne soit pas implémenté dans toutes les LIB. Vous pouvez essayer pthread_mutex_recursive_np, ou vous pouvez faire quelque chose de fantaisie pour contourner cela.

Il semble que le Pthread Mutex n'est pas réentrant. Vous pouvez contourner cela avec un drapeau indiquant si votre fil a déjà verrouillé le mutex:

bool haveLock = false;// thread variable
pthread_mutex_t waiting_barcode_mutex; // also thread var

mylock()
{
   if( haveLock ) return; // no need to lock twice
   pthread_mutex_lock(&waiting_barcode_mutex);
   haveLock = true;
}

myunlock()
{
   haveLock = false;
   pthread_mutex_unlock(&waiting_barcode_mutex); // or whatever the unlock call is
}

Voici le code de travail testé sur Ubuntu 12.04 LTS sur mon Dell M6300:

  pthread_mutex_t mutex;
  pthread_mutexattr_t attr;
  int rc = pthread_mutexattr_init(&attr);
    if (rc != 0)
        throw (L"pthread_mutexattr_init returns " + rc);
    rc = pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE_NP);
    if (rc != 0)
        throw (L"pthread_mutexattr_settype returns " + rc);
    rc = pthread_mutex_init (&mutex, &attr);
    if (rc != 0)
        throw (L"pthread_mutex_init returns " + rc);
    rc = pthread_mutexattr_destroy(&attr);
    if (rc != 0)
        throw (L"pthread_mutexattr_destroy returns " + rc);

   //first lock
   rc = pthread_mutex_lock(&mutex);
    if (rc != 0)
        throw (L"pthread_mutex_lock returns " + rc);
   //second lock
   rc = pthread_mutex_lock(&mutex);
    if (rc != 0)
        throw (L"pthread_mutex_lock returns " + rc);

N'oubliez pas de libérer le mutex autant de fois que vous l'avez acquis.

The code below shows that there is no problem in locking a critical section twice or thrice or N times before calling the unlock on pthread. You can do multiple locks on the same thread successively before unlocking without worrying but mind you, IT IS NOT a good programmer's practice. The right way is to call lock(), let the thread execute the critical section and call unlock(), so that other threads can execute the same piece of code between lock and unlock (called, critical section). The code below prevents any programmer's mishaps using ATTRIBUTES on pthread).

Read on!

// Example program using a thread locking multiple times sequentially before unlocking
#include <iostream>

using namespace std;

pthread_mutexattr_t     _attr;
pthread_mutex_t         _mutex;

///
/// Initialize mutex with error return locking mechanism (does not block
/// its own thread if multiple locks occurs.
///
void InitMutex()
{
   // Initialize mutex
   int ret=0;
   ret = pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_ERRORCHECK_NP);   // PTHREAD_MUTEX_ERRORCHECK_NP avoids double locking on same thread.
   if(ret != 0)
   {
      printf("Mutex attribute not initialized!!\n");
   }
   ret = pthread_mutex_init(&_mutex, &_attr);
   if(ret != 0)
   {
      printf("Mutex not initialized!!\n");
   }
}

///
/// Locks the critical section
///
int lock_me()
{
   return pthread_mutex_lock(&_mutex);
}

///
/// Unlocks the critical section
///
int unlock_me()
{
   return pthread_mutex_unlock(&_mutex);
}

int main()
{
  InitMutex(); // Very important
  int ret = 0;

  ret = lock_me();    // return value of 0 - OK
  cout << "First lock returns: "<< ret<< endl;
  ret = lock_me();    // returns a value like 35 - ERROR, but ignores locking again
  cout << "Second lock returns: "<< ret<< endl;

  // Do something in this critical section. No other thread can execute this at this time before unlock. Other threads (if any) wait at lock() waiting for main function to unlock() first.

  ret = unlock_me();  // unlocks the critical section. All is OK
  cout << "First unlock returns: "<< ret<< endl;
  ret = unlock_me();  // returns error value of 1, nothing to lock
  cout << "Second unlock returns: "<< ret<< endl;
  ret = unlock_me();  // same as above, nothing to do. Ignore and move on!
  cout << "Third unlock returns: "<< ret << endl;

  // The main() thread will never have a race condition ;) All iz well!!

  pthread_mutexattr_destroy(&_attr);    // clean up the mutex attribute
  pthread_mutex_destroy(&_mutex);       // clean up the mutex itself

}

OUTPUT:

First lock returns: 0

Second lock returns: 35

First unlock returns: 0

Second unlock returns: 1

Third unlock returns: 1

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top