質問

埋め込まれたLinux OS(UCLINUX)でアプリケーションを開発していますが、Mutexを複数回ロックできる必要があります(同じスレッドで)。

MutexとMutexattrが次のように定義および初期化されています。

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

しかし、私がロックを2回取得しようとすると、2番目のロックでブロックされます。

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

私はそれを間違って初期化していますか、それとも同じことを達成するより良い方法がありますか?

前もって感謝します。

結論:

  • どうやらpthread_mutex_recursiveまたはpthread_mutex_recursive_npが機能しないので、リエントラントミューテックスを作成できません。
  • try_lockも良くありません。可能であればロックを取得し、ロックを取得できない場合はエラーを返します。残念ながら、このエラーは、ミューテックスがすでに使用されていることを私に知らせているだけで、現在のスレッドがすでにロックを所有しているかどうかはわかりません。
  • PTHREAD_MUTEX_LOCK現在のスレッドにロックがある場合、エラーを返すことができますが、そのためには、型pthread_mutex_errorcheckのミューテックスを作成する必要があります。また、作成することもできません。
役に立ちましたか?

解決 5

(私はこの質問を答えたようにマークしなかったことに気付いた)

質問の結論から取られた:

  • どうやらpthread_mutex_recursiveまたはpthread_mutex_recursive_npが機能しないので、リエントラントミューテックスを作成できません。
  • try_lockも良くありません。可能であればロックを取得し、ロックを取得できない場合はエラーを返します。残念ながら、このエラーは、ミューテックスがすでに使用されていることを私に知らせているだけで、現在のスレッドがすでにロックを所有しているかどうかはわかりません。
  • PTHREAD_MUTEX_LOCK現在のスレッドにロックがある場合、エラーを返すことができますが、そのためには、型pthread_mutex_errorcheckのミューテックスを作成する必要があります。また、作成することもできません。

他のヒント

これはあなたが期待することをしていませんか?

最初のコールはロックを取得し、2番目のコールは最初のロックが解放されるまでブロックします(pthread_mutex_unlock)。これがロックが行うことです。

ドキュメントから:

「ミューテックスが既にロックされている場合、呼び出しのスレッドは、ミューテックスが使用可能になるまでブロックします。」

おそらくあなたは望んでいます pthread_mutex_trylock?あなたが何を達成しようとしているかを知らない限り、言うのは難しいです。

修正:

PTHREAD_MUTEX_RECURSIVEを設定していることがわかりませんでした....これについてもう少し考えてみましょう。

考えた後:

Google CodeSearchの周りを突くと、PTHREAD_MUTEX_RECURSIVEはすべてのLIBに実装されていないようです。 pthread_mutex_recursive_npを試すか、これを回避するために何か空想をすることができます。

pthreadの変異は再移植されていないようです。スレッドがすでにミューテックスをロックしているかどうかを示すフラグでこれを回避できます。

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
}

Dell M6300のUbuntu 12.04 LTSでテストされた作業コードがあります。

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

Mutexを取得したと同じくらい何度もリリースすることを忘れないでください。

以下のコードは、PTHREADでロック解除を呼び出す前に、重要なセクションを2回または3回またはn回ロックすることに問題がないことを示しています。心配することなくロック解除する前に、同じスレッドで複数のロックを連続して実行することができますが、気にしてください。それは良いプログラマーの練習ではありません。正しい方法は、lock()を呼び出し、スレッドをクリティカルセクションを実行してロックを呼び出すことです。以下のコードは、pthreadの属性を使用してプログラマーの事故を防ぎます)。

読む!

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

}

出力:

最初のロックリターン:0

2番目のロックリターン:35

最初にロック解除リターン:0

2番目のロック解除リターン:1

サードロック解除リターン:1

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top