Linuxスレッド同期の反発量(mutex)


反発量(反発ロックとも呼ばれる)は、POSIXスレッド規格から出ており、同じプロセス内の各スレッドを同期するために使用することができる.もちろん、1つの反発量が複数のプロセスが共有するメモリ領域に格納されている場合、反発量によってプロセス間の同期を行うこともできます.
反発量は、文字通り互いに反発するという意味であることがわかり、臨界領域(共有リソース)を保護し、いつでも1つのスレッドだけが共有リソースにアクセスできるようにするための最も基本的な同期ツールである.
反発量タイプはpthreadとして宣言されます.mutex_tデータ型は、に具体的な定義があります.
1反発量の初期化と破棄
/* Initialize a mutex.  */
int pthread_mutex_init (pthread_mutex_t *__mutex,\
                        __const pthread_mutexattr_t *__mutexattr);

/* Destroy a mutex.  */
int pthread_mutex_destroy (pthread_mutex_t *__mutex);

上記の2つの関数は,それぞれ反発量の初期化と破棄に起因する.
反発量が静的に割り当てられている場合は、次のように定数で初期化できます.
pthread_mutex_t mlock = PTHREAD_MUTEX_INITIALIZER;

もちろんpthread_でもmutex_Init()を初期化します.動的に割り当てられた反発量は、直接値を与えて初期化することができないため、このような方法で初期化するしかありません.pthread_mutex_Init()の2番目のパラメータは反発量のプロパティであり、デフォルトのプロパティ設定を使用するとNULLを入力できます.
反発量を使用する必要がない場合はpthread_を呼び出す必要があります.mutex_destroy()は、反発量が占有するリソースを破棄します.
2反発量の属性設定
/*            */
int pthread_mutexattr_init (pthread_mutexattr_t *__attr);

/*            */
int pthread_mutexattr_destroy (pthread_mutexattr_t *__attr);

/*                      */
int pthread_mutexattr_getpshared (__const pthread_mutexattr_t *__restrict __attr, \
                                   int *__restrict __pshared);

/*          ,           */
int pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr, int __pshared);

反発量初期化時pthread_mutex_Initの2番目のパラメータは反発量のプロパティであり、NULL空のポインタの場合はデフォルトのプロパティが使用されます.
反発量プロパティのデータ型はpthread_です.mutexattr_t,その初期化と破壊と反発量は類似している.反発量プロパティオブジェクトが初期化されると、異なる関数を呼び出して特定のプロパティを有効または禁止できます.特定のプロパティを設定する関数を示します:pthread_mutexattr_setpsharedは、異なるプロセス間で反発量を共有することを指定するために使用できます.これにより、反発量によって異なるプロセスを同期することができます.もちろん、この反発量がプロセス間の共有メモリ領域にあることを前提としています.
pthread_mutexattr_setpshared()関数の2番目のパラメータ_psharedは、プロセス間共有の有無を設定するために使用され、その値はPTHREAD_であってもよい.PROCESS_PRIVATEまたはPTHREAD_PROCESS_SHARED,後者はプロセス間共有を設定する.
次に、反発量をプロセス間で共有できるようにする大まかなプロセスを示します.
pthread_mutex_t *pSharedMutex;  //           
pthread_mutexattr_t mutexAttr;  //     

pSharedMutex = /*            */;

pthread_mutexattr_init(&mutexAttr);
pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(pSharedMutex, &mutexAttr);

3反発量の使用
/* Try locking a mutex.  */
int pthread_mutex_trylock (pthread_mutex_t *__mutex);

/* Lock a mutex.  */
int pthread_mutex_lock (pthread_mutex_t *__mutex);

/* Unlock a mutex.  */
int pthread_mutex_unlock (pthread_mutex_t *__mutex);

これらの関数はすべて簡単で、pthread_を通じてmutex_lock()関数は共有リソースにアクセスする権限を取得し、他のスレッドが反発量をロックしている場合、スレッドが反発量を指定してロックを解除するまでブロックします. pthread_mutex_trylock()は対応する非ブロッキング関数であり、反発量が占有されている場合、EBUSYエラーが返されます.共有リソースへのアクセスが完了したら、pthread_を使用してください.mutex_unlock()関数は,占有する反発量を解放する.他のスレッドがリソースにアクセスできるようにします.
ここで強調するのは,反発量は鍵をかけるために用いられ,待つために用いられないことである.
簡単に言えば、反発量の使用プロセスは、スレッドが反発量を占有し、共有リソースにアクセスし、最後に反発量を解放することです.スレッドが反発量を占有し、リソースが使用可能かどうかを判断し、使用できない場合は反発量を解放し、上記の手順を繰り返します.このような行為を回転やポーリングと呼び,CPU時間を浪費する行為である.
次は、同期問題における古典的な生産者消費者問題をシミュレートするテストコードです.
#include 
#include 
#include 

#include 
#include 

using namespace std;

pthread_mutex_t mutex;
queue product;

void * produce(void *ptr)
{
    for (int i = 0; i < 10; ++i)
    {
        pthread_mutex_lock(&mutex);
        product.push(i);
        pthread_mutex_unlock(&mutex);

        //sleep(1);
    }
}

void * consume(void *ptr)
{
    for (int i = 0; i < 10;)
    {
        pthread_mutex_lock(&mutex);

        if (product.empty())
        {
            pthread_mutex_unlock(&mutex);
            continue;
        }
     
        ++i;
        cout<
上記コードは、
consume
キューにデータがあるかどうかを判断するときにポーリングで行うのはもったいない行為です
CPU
リソースは、条件変数によってこの問題を解決することができます.Jun 25, 2013 PM 23:32 @Library