Frage

Ich entwickle eine Anwendung auf einem eingebetteten Linux -Betriebssystem (UCLINUX) und muss in der Lage sein, den Mutex mehr als einmal (mit demselben Thread) zu sperren.

Ich habe einen Mutex und eine mutexattr definiert und initialisiert wie folgt:

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);

Aber wenn ich versuche, das Schloss zweimal zu erwerben, blockiert es im zweiten Schloss:

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

Initialisiert ich es falsch oder gibt es eine bessere Möglichkeit, dasselbe zu erreichen?

Danke im Voraus.

Schlussfolgerungen:

  • Anscheinend funktioniert pthread_mutex_recursive oder pthread_mutex_recursive_np nicht, sodass ich keine Wiedereintritts -Mutex erstellen kann.
  • Try_lock ist auch nicht gut. Es erwirbt das Schloss, wenn es kann, und gibt einen Fehler zurück, wenn es das Schloss nicht erwerben kann. Leider informiert mich der Fehler nur, dass der Mutex bereits verwendet wird und ich nicht herausfinden kann, ob der aktuelle Thread das Sperre bereits besitzt oder nicht.
  • pThread_mutex_lock kann einen Fehler zurückgeben, wenn der aktuelle Thread die Sperre hat, aber ich muss ein Mutex des Typs pthread_mutex_errorcheck erstellen, und ich kann auch keinen erstellen.
War es hilfreich?

Lösung 5

(Ich habe gerade festgestellt, dass ich diese Frage nicht wie beantwortet markierte)

Entnommen aus den Schlussfolgerungen in der Frage:

  • Anscheinend funktioniert pthread_mutex_recursive oder pthread_mutex_recursive_np nicht, sodass ich keine Wiedereintritts -Mutex erstellen kann.
  • Try_lock ist auch nicht gut. Es erwirbt das Schloss, wenn es kann, und gibt einen Fehler zurück, wenn es das Schloss nicht erwerben kann. Leider informiert mich der Fehler nur, dass der Mutex bereits verwendet wird und ich nicht herausfinden kann, ob der aktuelle Thread das Sperre bereits besitzt oder nicht.
  • pThread_mutex_lock kann einen Fehler zurückgeben, wenn der aktuelle Thread die Sperre hat, aber ich muss ein Mutex des Typs pthread_mutex_errorcheck erstellen, und ich kann auch keinen erstellen.

Andere Tipps

Tut das nicht das, was Sie erwarten würden?

Der erste Anruf erwirbt das Schloss, und der zweite blockiert bis zum ersten Schloss veröffentlicht (pthread_mutex_unlock). Das machen Schlösser.

Aus der Dokumentation:

"Wenn der Mutex bereits gesperrt ist, blockiert der aufrufende Thread, bis der Mutex verfügbar ist."

Vielleicht willst du pthread_mutex_trylock? Es ist schwer zu sagen, wenn wir nicht wissen, was Sie erreichen möchten.

KORREKTUR:

Ich habe nicht gesehen, dass Sie PThread_Mutex_Recursive festgelegt haben. Lassen Sie mich noch etwas darüber nachdenken.

Nach dem Denken:

Aus Google -Codesarch -Stöbern sieht es so aus, als ob pThread_mutex_recursive nicht in allen LIBs implementiert ist. Sie können pthread_mutex_recursive_np versuchen, oder Sie haben möglicherweise etwas Schicksals, um dies zu umgehen.

Es klingt so, als ob der PThread -Mutex nicht wieder eingetreten ist. Sie könnten dies mit einem Flag umgeben, das angibt, ob Ihr Thread den Mutex bereits gesperrt hat:

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
}

Hier wird der Arbeitscode auf Ubuntu 12.04 LTS auf meinem Dell M6300 getestet:

  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);

Vergessen Sie nicht, den Mutex so oft freizulassen, wie Sie ihn erworben haben.

Der folgende Code zeigt, dass es kein Problem gibt, einen kritischen Abschnitt zweimal oder dreimal oder n -mal zu sperren, bevor das Entsperren auf PThread aufgerufen wird. Sie können mehrere Schlösser auf demselben Thread nacheinander ausführen, bevor Sie sich ohne Sorgen umrunden, aber Sie haben es um Sie. Es ist keine gute Programmierpraxis. Der richtige Weg besteht darin, Lock () aufzurufen, den Thread den kritischen Abschnitt ausführen und Unlock () aufrufen, damit andere Threads das gleiche Code -Stück zwischen Sperre und Entsperren (als kritischer Abschnitt genannt) ausführen können. Der folgende Code verhindert die Pannen eines Programmierers unter Verwendung von Attributen auf pThread).

Weiter lesen!

// 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

}

AUSGANG:

Erstes Schloss kehrt zurück: 0

Zweites Schloss Rückgabe: 35

Zuerst entsperren Returns: 0

Zweite Entsperren returns: 1

Dritte Entsperren Returns: 1

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top