3

main がミューテックス呼び出しを初期化するプロセスがあります。

MutexInit( pthread_mutex_t *Mutex )
{
    pthread_mutexattr_t mattr;

    pthread_mutexattr_init(&mattr);
    pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_ERRORCHECK_NP);

    #ifndef _POSIX_THREAD_PROCESS_SHARED
    #error "This platform does not support process shared mutex!"
    #else
    pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
    #endif

    pthread_mutex_init( Mutex, &mattr );
}

main最初にミューテックス M1 をロックし、次にスレッド T1 と T2 を作成します。

T1 が開始され、いくつかの作業が行われます。T2 が開始され、何か他のことを行い、ある時点でそのミューテックス M1 をロックします。ミューテックス タイプは PTHREAD_MUTEX_ERRORCHECK_NP であるため、T2 はブロックされません。代わりに、ミューテックス M1 が既にロックされていることを示すエラー EDEADLK が返されます。そのため、T2 は引き続きロックを試みます。ここまでは問題ありません。

その後、T1 は M1 のロックを解除するポイントに到達しますが、T1 はミューテックスを所有していない!?というエラー EPERM が返されます。したがって、T2 がロック解除されることはありません。

から属性の設定を削除するとMutexInit:

pthread_mutexattr_init(&mattr);
pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_ERRORCHECK_NP);

#ifndef _POSIX_THREAD_PROCESS_SHARED
#error "This platform does not support process shared mutex!"
#else
pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
#endif

および呼び出しpthread_mutex_init( Mutex, NULL );、つまり。デフォルトの属性、すべて正常に動作しています!

MutexInitプロセス全体で (共有メモリを介して) ミューテックスも使用しているため、初期ルーチンが必要です。

誰にもアイデアはありますか?私は非常に多くの記事や投稿を読んだので、どんな助けも感謝します.

編集:パオロのコードの修正版を使用して、私の観察を実証します:

これは、「私の順序付け」に合わせて Paolo のコードを修正したものです。

#include <stddef.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <semaphore.h>

pthread_mutex_t m;
sem_t s1, s2;

void print(const char *s, int err)
{
    printf("%s %d %s\n", s, err, strerror(err));
}

void *start_t1(void *arg)
{
    sem_wait(&s1); // <-t2
    print("t1: unlock ", pthread_mutex_unlock(&m));
    sem_post(&s2); //->t2
}

void *start_t2(void *arg)
{
    sem_wait(&s2); // <-main
    print("t2: lock ", pthread_mutex_lock(&m));
    sem_post(&s1); // ->t1

    sem_wait(&s2); // <-t1
    sem_post(&s1); // ->main
}

void main(void)
{
    pthread_mutexattr_t mattr;
    pthread_mutexattr_init(&mattr);
    pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_ERRORCHECK_NP);
    pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);

    sem_init(&s1, 0, 0);
    sem_init(&s2, 0, 0);

    print("main init", pthread_mutex_init(&m, &mattr));

    pthread_t t2, t1;
    pthread_create(&t1, NULL, start_t1, NULL);
    pthread_create(&t2, NULL, start_t2, NULL);

    sem_post(&s2); // ->t2
    sem_wait(&s1); // <-t2

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
}

出力は次のとおりです。

main init 0 Success
t2: lock  0 Success
t1: unlock  1 Operation not permitted

タイプが原因で、T1 がミューテックスのロックを解除できるようになると思いPTHREAD_PROCESS_SHAREDます。私が間違っている ?

ミューテックスの初期化がデフォルトに変更された場合 ( pthread_mutex_init(&m, **NULL**))、機能しています。

main init 0 Success
t2: lock  0 Success
t1: unlock  0 Success

ある種の逆論理のようです !

4

2 に答える 2

2

のPOSIXマニュアルページにpthread_mutexattr_setpshared(3)は次のように書かれています:

プロセス共有属性はPTHREAD_PROCESS_SHAREDに設定され、ミューテックスが割り当てられているメモリにアクセスできる任意のスレッドがミューテックスを操作できるようにします。これは、ミューテックスが複数のプロセスによって共有されるメモリに割り当てられている場合でも同様です。 プロセス共有属性がPTHREAD_PROCESS_PRIVATEの場合、mutex は、mutex を初期化したスレッドと同じプロセス内で作成されたスレッドによってのみ操作されます。異なるプロセスのスレッドがそのようなミューテックスで操作を試みた場合、動作は未定義です。属性のデフォルト値はPTHREAD_PROCESS_PRIVATEです。

この属性の目的は、異なるプロセスが (共有メモリを使用して) 同じpthread_mutex_tオブジェクトにアクセスできるようにすることだけです。実際の同期セマンティクスが変更されることはありません。考えてみると、同期プリミティブ (pthread_mutex_tオブジェクト) の目的は何になるでしょうか。このようなアナーキーは、マルチスレッド プログラムの設計にはほとんど当てはまりません。

于 2013-07-30T03:23:35.173 に答える