2013-07-18 94 views
3

我有一種方法,其中主要初始化互斥主叫:Pthread互斥(未)鎖定在不同的線程

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未被阻塞,而是返回錯誤EDEADLK,表示互斥體M1已被鎖定。所以T2繼續嘗試鎖定。目前爲止沒有問題。

然後T1來到它解鎖M1的地步,但錯誤EPERM返回,說T1不擁有互斥!所以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的代碼修改後的版本,以證明我的觀察:

這是一個的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_mutex_init(&m, **NULL**)),則表明它正在工作。

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

似乎是某種倒置的邏輯!

+0

這對我來說是死鎖(Ubuntu 13.04在Virtualbox/Win7上運行)。第一個'sem_wait(&s1)'永遠不會返回。這可以通過在'sem_wait(&s1)''之前'''''''''''''''''''''''''''''''' – FooF

回答

1

這不是我所看到的......請注意,EPERM是T2應該返回的內容,而不是T1。另一方面,如果你遞歸地鎖定相同的互斥鎖,EDEADLK就是T1應該返回的東西。

這是我用於測試的代碼:

#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_t2(void *arg) 
{ 
    print("t2", pthread_mutex_unlock(&m)); 
    sem_post(&s1); 
    sem_wait(&s2); 
} 

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); 
    pthread_mutex_init(&m, &mattr); 

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

    print("t1", pthread_mutex_lock(&m)); 

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

    sem_wait(&s1); 
    print("t1", pthread_mutex_unlock(&m)); 
    sem_post(&s2); 
    pthread_join(t2, NULL); 
} 
+0

感謝您的快速和簡單的迴應!如果你不介意我會把你的代碼和修改,以適應「我的序列」,並更新到帖子... – MlaKe

+0

看起來像你想要的是一個二進制信號量,而不是一個互斥量。 –

1

POSIX爲pthread_mutexattr_setpshared(3)手冊頁說:

進程共享屬性被設置爲PTHREAD_PROCESS_SHARED以允許互斥由任何有權訪問分配互斥量的內存的線程來操作,即使互斥鎖被分配到多進程共享的內存中。如果進程共享的屬性爲PTHREAD_PROCESS_PRIVATE,互斥量只能由與初始化互斥量的線程在同一進程內創建的線程操作;如果不同進程的線程試圖對這樣的互斥量進行操作,則行爲是不確定的。屬性的默認值應爲PTHREAD_PROCESS_PRIVATE

該屬性的目的只是爲了允許不同的進程(通過共享內存)訪問同一個對象pthread_mutex_t。暗示實際同步語義沒有變化。當你考慮它的時候,如果每個線程都可以鎖定和解鎖,那麼同步原語(pthread_mutex_t對象)的目的是什麼。這種無政府狀態在多線程程序設計中幾乎沒有地位!