天天看點

Linux多線程5-3_線程的同步屬性

一、互斥量的屬性

    就像線程有屬性一樣,線程的同步互斥量也有屬性,比較重要的是程序共享屬性和類型屬性。互斥量的屬性用pthread_mutexattr_t類型的資料

    表示,當然在使用之前必須進行初始化,使用完成之後需要進行銷毀:

    1)、互斥量初始化

    int pthread_mutexattr_init(pthread_mutexattr_t *attr);

    2)、互斥量銷毀

     int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);

二、互斥量的程序共享屬性

    程序共享屬性有兩種值:

    1)、PTHREAD_PROCESS_PRIVATE,這個是預設值,同一個程序中的多個線程通路同一個同步對象

    2)、PTHREAD_PROCESS_SHARED, 這個屬性可以使互斥量在多個程序中進行同步,如果互斥量在多程序的共享記憶體區域,那麼具有這個屬性的

            互斥量可以同步多程序

    設定互斥量程序共享屬性

      int pthread_mutexattr_getpshared(const pthread_mutexattr_t *restrict attr, int *restrict pshared);

      int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared);

    程序共享屬性需要檢測系統是否支援,可以檢測宏_POSIX_THREAD_PROCESS_SHARED

三、互斥量的類型屬性

    類型屬性

    互斥量類型                             沒有解鎖時再次加鎖     不占用是解鎖          已解鎖時解鎖

    PTHREAD_MUTEX_NORMAL                 死鎖                 未定義                       未定義

    PTHREAD_MUTEX_ERRORCHEK            傳回錯誤          傳回錯誤                    傳回錯誤

    PTHREAD_MUTEX_RECURSIVE             允許                 傳回錯誤                    傳回錯誤

    PTHREAD_MUTEX_DEFAULT                未定義              未定義                       未定義

    擷取/設定互斥量的類型屬性

       int pthread_mutexattr_gettype(const pthread_mutexattr_t *restrict attr, int *restrict type);

       int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);

四、讀寫鎖與條件變量的屬性

    1、讀寫鎖也有屬性,它隻有一個程序共享屬性

        讀寫鎖屬性初始化

           int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr);

           int pthread_rwlockattr_init(pthread_rwlockattr_t *attr);

        設定讀寫鎖程序共享屬性

           int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *restrict attr, int *restrict pshared);

           int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr, int pshared); 

    2、條件變量也有程序共享屬性

        條件變量屬性初始化

           int pthread_condattr_destroy(pthread_condattr_t *attr);

           int pthread_condattr_init(pthread_condattr_t *attr);

        設定條件變量屬性

           int pthread_condattr_getpshared(const pthread_condattr_t *restrict attr, int *restrict pshared);

           int pthread_condattr_setpshared(pthread_condattr_t *attr, int pshared);

五、手冊

PTHREAD_MUTEXATTR_DESTROY(3POSIX Programmer’s ManPTHREAD_MUTEXATTR_DESTROY(3P)

PROLOG

       This  manual page is part of the POSIX Programmer’s Manual.  The Linux implementation of this interface may differ (con-

       sult the corresponding Linux manual page for details of Linux behavior), or the interface  may  not  be  implemented  on

       Linux.

        //這隻是POSIX的手冊,Linux對這個接口的實作可能不一樣,或者有的根本沒有實作這個接口

NAME

       pthread_mutexattr_destroy, pthread_mutexattr_init - destroy and initialize the mutex attributes object

        //初始化或者銷毀互斥量的屬性

SYNOPSIS

       #include

        //頭檔案

       int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);

       int pthread_mutexattr_init(pthread_mutexattr_t *attr);

DESCRIPTION

       The  pthread_mutexattr_destroy() function shall destroy a mutex attributes object; the object becomes, in effect, unini-

       tialized. An implementation may cause pthread_mutexattr_destroy() to set the object referenced by  attr  to  an  invalid

       value.  A destroyed attr attributes object can be reinitialized using pthread_mutexattr_init(); the results of otherwise

       referencing the object after it has been destroyed are undefined.

        //pthread_mutexattr_destroy()會銷毀一個互斥量屬性,這個屬性将變成一個沒有被初始化的值。或者有的實作可能導緻

        //互斥量的屬性是一個無效的值。一個已經被銷戶的互斥量屬性可以重新被初始化,使用一個已經被銷毀的屬性會導緻未

        //知的結果

       The pthread_mutexattr_init() function shall initialize a mutex attributes object attr with the default value for all  of

       the attributes defined by the implementation.

        //pthread_mutexattr_init()初始化一個互斥量的屬性

       Results are undefined if pthread_mutexattr_init() is called specifying an already initialized attr attributes object.

        //如果初始化一個已經被初始化過的屬性,那麼結果是未知的

       After  a  mutex attributes object has been used to initialize one or more mutexes, any function affecting the attributes

       object (including destruction) shall not affect any previously initialized mutexes.

        //對于已經初始化的屬性,不會影響以前的互斥量

RETURN VALUE

       Upon successful completion, pthread_mutexattr_destroy() and pthread_mutexattr_init() shall return  zero;  otherwise,  an

       error number shall be returned to indicate the error.

        //成功傳回0,失敗傳回錯誤碼

ERRORS

       The pthread_mutexattr_destroy() function may fail if:

        //pthread_mutexattr_destroy() 在以下情況失敗

       EINVAL The value specified by attr is invalid.

                    //屬性值是無效的

       The pthread_mutexattr_init() function shall fail if:

       // pthread_mutexattr_init()會在以下情況失敗

       ENOMEM Insufficient memory exists to initialize the mutex attributes object.

                      //沒有記憶體去初始化屬性

       These functions shall not return an error code of [EINTR].

        //不會傳回EINTR

PTHREAD_MUTEXATTR_GETPSHAREPOSIX Programmer’s PTHREAD_MUTEXATTR_GETPSHARED(3P)

       pthread_mutexattr_getpshared, pthread_mutexattr_setpshared - get and set the process-shared attribute

        //擷取或者設定互斥量的程序共享屬性

       int pthread_mutexattr_getpshared(const pthread_mutexattr_t *  restrict attr, int *restrict pshared);

       int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared);

       The  pthread_mutexattr_getpshared()  function shall obtain the value of the process-shared attribute from the attributes

       object referenced by attr. The pthread_mutexattr_setpshared() function shall set the process-shared attribute in an ini-

       tialized attributes object referenced by attr.

        //pthread_mutexattr_getpshared()會擷取到互斥量的程序共享屬性,pthread_mutexattr_setpshared()可以設定互斥量的程序

        //共享屬性

       The  process-shared  attribute is set to PTHREAD_PROCESS_SHARED to permit a mutex to be operated upon by any thread that

       has access to the memory where the mutex is allocated, even if the mutex is allocated in memory that is shared by multi-

       ple  processes.  If  the  process-shared  attribute is PTHREAD_PROCESS_PRIVATE, the mutex shall only be operated upon by

       threads created within the same process as the thread that initialized the mutex;  if  threads  of  differing  processes

       attempt  to operate on such a mutex, the behavior is undefined. The default value of the attribute shall be PTHREAD_PRO-

       CESS_PRIVATE.

        //程序共享屬性是PTHREAD_PROCESS_SHARED,這樣會允許互斥量在任何不同的線程之間同步資料,甚至這兩個線程不在同一個

        //程序裡。 如果屬性是PTHREAD_PROCESS_PRIVATE,那麼互斥量僅僅允許在同一程序範圍内同步資料,如果不同程序之間同步資料

        //那麼結果是未知的。預設的屬性是 PTHREAD_PROCESS_PRIVATE

       Upon successful completion, pthread_mutexattr_setpshared() shall return  zero;  otherwise,  an  error  number  shall  be

       returned to indicate the error.

       Upon  successful  completion, pthread_mutexattr_getpshared() shall return zero and store the value of the process-shared

       attribute of attr into the object referenced by the pshared parameter. Otherwise, an error number shall be  returned  to

       indicate the error.

        //成功傳回0,而且互斥量的程序共享屬性被儲存起來,否則傳回錯誤碼

       The pthread_mutexattr_getpshared() and pthread_mutexattr_setpshared() functions may fail if:

        //在以下情況失敗

                    //屬性值是無效的

       The pthread_mutexattr_setpshared() function may fail if:

        //pthread_mutexattr_setpshared()會在以下情況失敗

       EINVAL The new value specified for the attribute is outside the range of legal values for that attribute.

                    //設定的屬性值不在規定範圍之内

PTHREAD_MUTEXATTR_GETTYPE(3POSIX Programmer’s ManPTHREAD_MUTEXATTR_GETTYPE(3P)

       pthread_mutexattr_gettype, pthread_mutexattr_settype - get and set the mutex type attribute

        //擷取或者設定互斥量的類型

       The  pthread_mutexattr_gettype()  and  pthread_mutexattr_settype()  functions, respectively, shall get and set the mutex

       type attribute. This attribute is set in the type parameter to these functions. The default value of the type  attribute

       is PTHREAD_MUTEX_DEFAULT.

        // pthread_mutexattr_gettype()  and  pthread_mutexattr_settype() 擷取或者設定互斥量的類型。類型會在參數中設定,預設的

        //屬性是PTHREAD_MUTEX_DEFAULT.

       The type of mutex is contained in the type attribute of the mutex attributes. Valid mutex types include:

        //互斥量的類型包含在它的屬性中,有效的類型包括:

       PTHREAD_MUTEX_NORMAL

              This  type of mutex does not detect deadlock. A thread attempting to relock this mutex without first unlocking it

              shall deadlock.  Attempting to unlock a mutex locked  by  a  different  thread  results  in  undefined  behavior.

              Attempting to unlock an unlocked mutex results in undefined behavior.

              //這個類型不會檢測死鎖,當一個線程試圖加鎖一個還沒被解鎖的互斥量,那麼就可能死鎖。試圖解鎖被其他線程

              //鎖住的互斥量,結果是未知的。解鎖已經被解鎖的互斥量結果是未知的

       PTHREAD_MUTEX_ERRORCHECK

              This  type  of mutex provides error checking. A thread attempting to relock this mutex without first unlocking it

              shall return with an error. A thread attempting to unlock a mutex which another thread has  locked  shall  return

              with an error. A thread attempting to unlock an unlocked mutex shall return with an error.

              //這個類型會提供錯誤檢測。當一個線程試圖加鎖一個還沒被解鎖的互斥量,那麼就會傳回錯誤碼。試圖解鎖被其他線程

              //鎖住的互斥量,傳回錯誤。解鎖已經被解鎖的互斥量,傳回錯誤

       PTHREAD_MUTEX_RECURSIVE

              A  thread  attempting  to  relock  this  mutex without first unlocking it shall succeed in locking the mutex. The

              relocking deadlock which can occur with mutexes of type PTHREAD_MUTEX_NORMAL  cannot  occur  with  this  type  of

              mutex.  Multiple locks of this mutex shall require the same number of unlocks to release the mutex before another

              thread can acquire the mutex. A thread attempting to unlock a mutex which another thread has locked shall  return

              with an error.  A thread attempting to unlock an unlocked mutex shall return with an error.

              //重新鎖住一個未解鎖的互斥量會成功。在正常情況下會造成死鎖,但是這種類型的卻不會。多次鎖住互斥量應該有對應的

              //多次解鎖操作。試圖解鎖被其他線程鎖住的互斥量,傳回錯誤。解鎖已經被解鎖的互斥量,傳回錯誤

       PTHREAD_MUTEX_DEFAULT

              Attempting  to  recursively lock a mutex of this type results in undefined behavior. Attempting to unlock a mutex

              of this type which was not locked by the calling thread results in undefined behavior.  Attempting  to  unlock  a

              mutex of this type which is not locked results in undefined behavior. An implementation may map this mutex to one

              of the other mutex types.

              //這種類型下,多次鎖住互斥量是未知的結果。試圖解鎖一個未加鎖的互斥量,結果是未知的。試圖去解鎖一個

              //其他線程加鎖的互斥量,結果是未知的。有的實作會将這種類型映射到其他類型

       Upon successful completion, the pthread_mutexattr_gettype() function shall return zero and store the value of  the  type

       attribute  of  attr  into the object referenced by the type parameter. Otherwise, an error shall be returned to indicate

       the error.

        //成功傳回0, pthread_mutexattr_gettype() 會儲存類型值,失敗傳回錯誤碼

       If successful, the pthread_mutexattr_settype() function shall return zero; otherwise, an error number shall be  returned

       to indicate the error.

       The pthread_mutexattr_settype() function shall fail if:

        //pthread_mutexattr_settype() 會在以下情況失敗

       EINVAL The value type is invalid.

                    //類型值無效

       The pthread_mutexattr_gettype() and pthread_mutexattr_settype() functions may fail if:

        //pthread_mutexattr_gettype() and pthread_mutexattr_settype() 在以下情況失敗

六、執行個體

    互斥量屬性使用

    1、程式架構

Linux多線程5-3_線程的同步屬性

    2、源代碼

點選(此處)折疊或打開

#include "apue.h"

int main()

{

    char *shm = "myshm";

    char *shm1 = "myshm1";

    int shm_id, shm_id1;

    char *buf;

    pid_t pid;

    pthread_mutex_t *mutex;

    pthread_mutexattr_t mutexattr;

    //打開共享記憶體

    shm_id1 = shm_open(shm1, O_RDWR|O_CREAT, 0644);

    //調整共享記憶體大小

    ftruncate(shm_id1, 100);

    //映射共享記憶體,MAP_SHARED屬性表明,對共享記憶體的任何修改都會影響其他程序

    mutex =(pthread_mutex_t *)mmap(NULL, 100, PROT_READ|PROT_WRITE, MAP_SHARED, shm_id1, 0);

    pthread_mutexattr_init(&mutexattr);

#ifdef _POSIX_THREAD_PROCESS_SHARED

    pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);

#endif

    pthread_mutex_init(mutex, &mutexattr);

    shm_id = shm_open(shm, O_RDWR|O_CREAT, 0644);

    ftruncate(shm_id, 100);

    buf =(char *)mmap(NULL, 100, PROT_READ|PROT_WRITE, MAP_SHARED, shm_id, 0);

    pid = fork();

    if(pid==0)

    {    

        //休眠1s,讓父程序先運作

        sleep(1);

        printf("I'm child proccess\n");

        pthread_mutex_lock(mutex);

        //将共享記憶體記憶體修改為hello

        memcpy(buf, "hello", 6);

        printf("child buf is : %s\n", buf);

        pthread_mutex_unlock(mutex);

    }

    else if(pid>0)

    {

        printf("I'm parent proccess\n");

        //修改共享記憶體到内容,改為world

        memcpy(buf, "world", 6);

        sleep(3);

        printf("parent buf is : %s\n", buf);

    pthread_mutexattr_destroy(&mutexattr);

    pthread_mutex_destroy(mutex);

    //解除映射

    munmap(buf, 100);

    //消除共享記憶體

    shm_unlink(shm);

    munmap(mutex, 100);

    shm_unlink(shm1);

}

繼續閱讀