1. 程式人生 > >C/C++_多核多執行緒程式設計_互斥鎖

C/C++_多核多執行緒程式設計_互斥鎖

前言

定義/概念

問題的出現

在現代作業系統中,出現不止一個物件(程序/執行緒)對程式碼進行訪問是一個普遍的現象(併發的來源),這也就會出現對共享的資源(記憶體、硬體資源等)出現競爭佔有的狀態(競態)。資源是必須用於多個物件共享的,但是我們又不能讓多個物件同時佔有資源(即競態的發生),那麼這時候就必須有一個操作,保證一個物件訪問資源時,其他物件無法訪問資源,這樣互斥鎖也就應運而生。
在系統設計,程式碼設計上,我們一直在避免競態的發生,比如將硬體記憶體對映為虛擬記憶體(避免程序間資源的訪問),比如將記憶體分為堆/棧/動態棧等(將資源存放的地方分開),比如將減少對全域性變數的定義(不讓其被更多物件訪問到)。通過互斥的操作,我們做到一次只有一個執行執行緒訪問共享的資源。

定義

互斥鎖:對資源進行鎖定,保證只有一個訪問者對資源進行訪問,但是無法限制訪問者對資源的訪問順序,訪問是無序的;

用法

環境

計算機語言:C++;
系統:Android N;

使用流程

對於互斥鎖的使用流程可以抽象為以下幾個步驟:

  • 建立 Create

  • 加鎖 Lock

  • 解鎖 Unlock

  • 銷燬 Destroy

在建立鎖之前,要新增標頭檔案:#include <pthread.h>
使用pthread_mutex_init()對鎖進行初始化;
使用pthread_mutex_lock()對鎖進行上鎖;
使用pthread_mutex_unlock()

對鎖進行解鎖;
使用pthread_mutex_destroy()對鎖進行銷燬;

函式具體說明

pthread_mutex_init

函式原型:int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
引數1:我們自己宣告的鎖變數;
引數2:新建的鎖的屬性,一般為空,使用預設的鎖型別,預設是快速互斥鎖;
該函式用於C函式的多執行緒程式設計中,對互斥鎖的動態初始化。
不同的鎖型別在試圖對一個已經被鎖定的互斥鎖加鎖時表現不同。

pthread_mutex_init()函式成功完成之後會返回零,其他任何返回值都表示出現了錯誤。

函式成功執行後,互斥鎖被初始化為未鎖住態。

pthread_mutexattr_init

函式原型:int pthread_mutexattr_init(pthread_mutexattr_t *mattr);
引數1:互斥鎖的屬性;
使用pthread_mutexattr_init()可以將與互斥鎖物件相關聯的屬性初始化為其預設值,也就是將pthread_mutex_init的引數2設定為預設值。在執行過程中,執行緒系統會為每個屬性物件分配儲存空間。

#include <pthread.h>

pthread_mutexattr_t mattr;

int ret;/* initialize an attribute to default value */

ret = pthread_mutexattr_init(&mattr);

呼叫此函式時,pshared 屬性的預設值為 PTHREAD_PROCESS_PRIVATE。 該值表示可以在程序內使用經過初始化的互斥鎖。
mattr 的型別為 opaque,其中包含一個由系統分配的屬性物件。mattr 範圍可能的值為 PTHREAD_PROCESS_PRIVATE 和 PTHREAD_PROCESS_SHARED。PTHREAD_PROCESS_PRIVATE 是預設值。
對於互斥鎖屬性物件,必須首先通過呼叫 pthread_mutexattr_destroy() 將其銷燬,才能重新初始化該物件。pthread_mutexattr_init() 呼叫會導致分配型別為 opaque 的物件。如果未銷燬該物件,則會導致記憶體洩漏。

pthread_mutexattr_destroy

函式原型:int pthread_mutexattr_destroy(pthread_mutexattr_t *mattr)
引數1:互斥鎖的屬性;
pthread_mutexattr_destroy()用來銷燬 pthread_mutexattr_init() 所建立的屬性物件的儲存空間。

#include <pthread.h>

pthread_mutexattr_t mattr;

int ret;/* destroy an attribute */

ret = pthread_mutexattr_init(&mattr);

ret = pthread_mutexattr_destroy(&mattr);

pthread_mutexattr_destroy() 成功完成之後會返回零。其他任何返回值都表示出現了錯誤。如果出現以下情況,該函式將失敗並返回對應的值。
EINVAL 描述: 由 mattr 指定的值無效。

pthread_mutexattr_setpshared

函式原型:int pthread_mutexattr_setpshared(pthread_mutexattr_t *mattr, int pshared);
引數1:互斥鎖的屬性;
引數2:指定互斥鎖的作用域的型別,有兩種,PTHREAD_PROCESS_PRIVATE和PTHREAD_PROCESS_SHARED預設是PTHREAD_PROCESS_PRIVATE;
pthread_mutexattr_setpshared()可用來設定互斥鎖變數的作用域。
互斥鎖變數可以是程序專用的(程序內)變數,也可以是系統範圍內的(程序間)變數。要在多個程序中的執行緒之間共享互斥鎖,可以在共享記憶體中建立互斥鎖,並將pshared屬性設定為 PTHREAD_PROCESS_SHARED。

#include <pthread.h>

pthread_mutexattr_t mattr;

int ret;

ret = pthread_mutexattr_init(&mattr); /* * resetting to its default value: private */

ret = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_PRIVATE);

pthread_mutexattr_getpshared

函式原型:int pthread_mutexattr_getpshared(pthread_mutexattr_t *mattr, int *pshared);
引數1:互斥鎖的屬性;
引數2:指定互斥鎖的作用域的型別,有兩種,PTHREAD_PROCESS_PRIVATE和PTHREAD_PROCESS_SHARED預設是PTHREAD_PROCESS_PRIVATE;

pthread_mutexattr_getpshared()可用來返回由 pthread_mutexattr_setpshared() 定義的互斥鎖變數的範圍。

此函式可為屬性物件 mattr 獲取 pshared 的當前值。該值為 PTHREAD_PROCESS_SHARED 或 PTHREAD_PROCESS_PRIVATE。

pthread_mutexattr_getpshared() 成功完成之後會返回零。其他任何返回值都表示出現了錯誤。如果出現以下情況,該函式將失敗並返回對應的值。

EINVAL 描述: 由 mattr 指定的值無效。


#include <pthread.h>

pthread_mutexattr_t mattr;

int pshared, ret;/* get pshared of mutex */

ret = pthread_mutexattr_getpshared(&mattr, &pshared);

pthread_mutexattr_settype

函式原型:int pthread_mutexattr_settype(pthread_mutexattr_t *attr , int type);
引數1:互斥鎖的屬性;
引數2:互斥鎖的type屬性,決定不同的鎖型別在試圖對一個已經被鎖定的互斥鎖加鎖時表現不同。
pthread_mutexattr_settype()可用來設定互斥鎖的type屬性。

型別屬性的預設值為 PTHREAD_MUTEX_DEFAULT。
type引數指定互斥鎖的型別。以下列出了有效的互斥鎖型別:

PTHREAD_MUTEX_NORMAL 描述: 此型別的互斥鎖不會檢測死鎖。如果執行緒在不首先解除互斥鎖的情況下嘗試重新鎖定該互斥鎖,則會產生死鎖。嘗試解除由其他執行緒鎖定的互斥鎖會產生不確定的行為。如果嘗試解除未鎖定的互斥鎖,則會產生不確定的行為。

PTHREAD_MUTEX_ERRORCHECK 描述: 此型別的互斥鎖可提供錯誤檢查。如果執行緒在不首先解除鎖定互斥鎖的情況下嘗試重新鎖定該互斥鎖,則會返回錯誤。如果執行緒嘗試解除鎖定的互斥鎖已經由其他執行緒鎖定,則會返回錯誤。如果執行緒嘗試解除未鎖定的互斥鎖,則會返回錯誤。

PTHREAD_MUTEX_RECURSIVE 描述: 如果執行緒在不首先解除鎖定互斥鎖的情況下嘗試重新鎖定該互斥鎖,則可成功鎖定該互斥鎖。 與 PTHREAD_MUTEX_NORMAL 型別的互斥鎖不同,對此型別互斥鎖進行重新鎖定時不會產生死鎖情況。多次鎖定互斥鎖需要進行相同次數的解除鎖定才可以釋放該鎖,然後其他執行緒才能獲取該互斥鎖。如果執行緒嘗試解除鎖定的互斥鎖已經由其他執行緒鎖定,則會返回錯誤。 如果執行緒嘗試解除未鎖定的互斥鎖,則會返回錯誤。

PTHREAD_MUTEX_DEFAULT 描述: 如果嘗試以遞迴方式鎖定此型別的互斥鎖,則會產生不確定的行為。對於不是由呼叫執行緒鎖定的此型別互斥鎖,如果嘗試對它解除鎖定,則會產生不確定的行為。對於尚未鎖定的此型別互斥鎖,如果嘗試對它解除鎖定,也會產生不確定的行為。允許在實現中將該互斥鎖對映到其他互斥鎖型別之一。對於 Solaris 執行緒,PTHREAD_PROCESS_DEFAULT 會對映到 PTHREAD_PROCESS_NORMAL。

如果執行成功,pthread_mutexattr_settype 函式會返回零。否則,將返回用於指明錯誤的錯誤號。

EINVAL 描述: 值為 type 無效。EINVAL 描述: attr 指定的值無效。

pthread_mutexattr_gettype

函式原型:int pthread_mutexattr_gettype(pthread_mutexattr_t *attr , int *type);
引數1:互斥鎖的屬性;
引數2:互斥鎖的type屬性,決定不同的鎖型別在試圖對一個已經被鎖定的互斥鎖加鎖時表現不同。
pthread_mutexattr_gettype()可用來獲取由 pthread_mutexattr_settype() 設定的互斥鎖的type屬性。

型別屬性的預設值為 PTHREAD_MUTEX_DEFAULT。

type引數指定互斥鎖的型別。有效的互斥鎖型別包括:

PTHREAD_MUTEX_NORMAL PTHREAD_MUTEX_ERRORCHECK PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_DEFAULT 有關每種型別的說明,請參見pthread_mutexattr_settype 語法。

如果成功完成,pthread_mutexattr_gettype() 會返回 0。其他任何返回值都表示出現了錯誤。

pthread_mutexattr_setprotocol

函式原型:int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol);
引數1:指示以前呼叫 pthread_mutexattr_init() 時建立的互斥鎖屬性物件;
引數2:protocol 可定義應用於互斥鎖屬性物件的協議;
pthread.h 中定義的 protocol 可以是以下值之一:PTHREAD_PRIO_NONE、PTHREAD_PRIO_INHERIT 或 PTHREAD_PRIO_PROTECT。
PTHREAD_PRIO_NONE :執行緒的優先順序和排程不會受到互斥鎖擁有權的影響。
PTHREAD_PRIO_INHERIT:此協議值會影響執行緒的優先順序和排程。如果更高優先順序的執行緒,如執行緒2 ,因 執行緒1 所擁有的一個或多個互斥鎖而被阻塞,而這些互斥鎖是用 PTHREAD_PRIO_INHERIT 初始化的,則 執行緒1 將以高於它的優先順序(擁有執行緒2 的優先順序)或者所有正在等待這些互斥鎖(這些互斥鎖是 執行緒1 所擁有的互斥鎖)的執行緒的最高優先順序執行。如果 執行緒1 因另一個執行緒 (執行緒3) 擁有的互斥鎖而被阻塞,則相同的優先順序繼承效應會以遞迴方式傳播給 執行緒3。使用 PTHREAD_PRIO_INHERIT 可以避免優先順序倒置。低優先順序的執行緒持有較高優先順序執行緒所需的鎖時,便會發生優先順序倒置,這樣可以保證持有鎖的執行緒以較高的優先順序執行。只有在較低優先順序的執行緒釋放該鎖之後,較高優先順序的執行緒才能繼續使用該鎖。如果為使用協議屬性值 PTHREAD_PRIO_INHERIT 初始化的互斥鎖定義了 _POSIX_THREAD_PRIO_INHERIT,則互斥鎖的屬主失敗時會根據pthread_mutexattr_setrobust_np() 的 robustness 引數的值做出相應的行為。
如果成功完成,pthread_mutexattr_setprotocol() 會返回 0。其他任何返回值都表示出現了錯誤。

如果出現以下任一情況,pthread_mutexattr_setprotocol() 將失敗並返回對應的值。

ENOSYS 描述: 選項 _POSIX_THREAD_PRIO_INHERIT 和 _POSIX_THREAD_PRIO_PROTECT 均未定義並且該實現不支援此函式。 ENOTSUP 描述: protocol 指定的值不受支援。 如果出現以下任一情況,pthread_mutexattr_setprotocol() 可能會失敗並返回對應的值。

EINVAL 描述: attr 或 protocol 指定的值無效。EPERM 描述: 呼叫方無權執行該操作。

pthread_mutexattr_getprotocol

pthread_mutexattr_getprotocol()可用來獲取互斥鎖屬性物件的協議屬性。
函式原型:int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol);
引數1:指示以前呼叫 pthread_mutexattr_init() 時建立的互斥鎖屬性物件;
引數2:protocol 包含以下協議屬性之一:PTHREAD_PRIO_NONE、PTHREAD_PRIO_INHERIT 或 PTHREAD_PRIO_PROTECT;
如果成功完成,pthread_mutexattr_getprotocol() 會返回 0。其他任何返回值都表示出現了錯誤。

如果出現以下情況,pthread_mutexattr_getprotocol() 將失敗並返回對應的值。

ENOSYS 描述: _POSIX_THREAD_PRIO_INHERIT 選項和 _POSIX_THREAD_PRIO_PROTECT 選項均未定義並且該實現不支援此函式。 如果出現以下任一情況,pthread_mutexattr_getprotocol() 可能會失敗並返回對應的值。

EINVAL 描述: attr 指定的值無效。EPERM 描述: 呼叫方無權執行該操作。

pthread_mutexattr_setprioceiling

函式原型:int pthread_mutexattr_setprioceiling(pthread_mutexatt_t *attr, int prioceiling, int *oldceiling);
引數1:指示以前呼叫 pthread_mutexattr_init() 時建立的互斥鎖屬性物件;
引數2:指定已初始化互斥鎖的優先順序上限。優先順序上限定義執行互斥鎖保護的臨界段時的最低優先順序。prioceiling 位於 SCHED_FIFO 所定義的優先順序的最大範圍內。要避免優先順序倒置(阻塞的執行緒優先順序高於持有鎖的優先順序),請將 prioceiling 設定為高於或等於可能會鎖定特定互斥鎖的所有執行緒的最高優先順序。
pthread_mutexattr_setprioceiling()可用來設定互斥鎖屬性物件的優先順序上限屬性。
看了下網上的資料,這裡的用法還不怎麼理解,還有一些是硬體不支援的,下面有個demo,示例測試系統支不支援這個特性:

int main(void)
{

    /* Make sure there is prioceiling capability. */
    /* #ifndef _POSIX_PRIORITY_SCHEDULING
       fprintf(stderr,"prioceiling attribute is not available for testing\n");
       return PTS_UNRESOLVED;
       #endif */

    pthread_mutexattr_t mta;
    int prioceiling, ret;

    prioceiling = sched_get_priority_min(SCHED_FIFO);

    /* Set the prioceiling of an unintialized mutex attr. */
    if ((ret = pthread_mutexattr_setprioceiling(&mta, prioceiling)) == 0) {
        printf
            ("Test PASSED: *Note: Returned 0 instead of EINVAL when passed an uninitialized mutex attribute object to pthread_mutexattr_setprioceiling, but standard says 'may' fail.\n");
        return PTS_PASS;
    }

    if (ret != EINVAL) {
        printf
            ("Test FAILED: Invalid return code %d. Expected EINVAL or 0.\n",
             ret);
        return PTS_FAIL;
    }

    printf("Test PASSED\n");
    return PTS_PASS;
}

如果成功完成,pthread_mutexattr_setprioceiling() 會返回 0。其他任何返回值都表示出現了錯誤。

如果出現以下任一情況,pthread_mutexattr_setprioceiling() 將失敗並返回對應的值。

ENOSYS 描述: 選項 _POSIX_THREAD_PRIO_PROTECT 未定義並且該實現不支援此函式。 如果出現以下任一情況,pthread_mutexattr_setprioceiling() 可能會失敗並返回對應的值。

EINVAL 描述: attr 或 prioceiling 指定的值無效。EPERM 描述: 呼叫方無權執行該操作。

pthread_mutexattr_getprioceiling

pthread_mutex_setprioceiling

pthread_mutex_getprioceiling

pthread_mutexattr_setrobust_np

pthread_mutexattr_getrobust_np

demo

多核多執行緒的demo留待下面文章來記錄。

相關推薦

【Linux C 執行程式設計互斥與條件變數

一、互斥鎖互斥量從本質上說就是一把鎖, 提供對共享資源的保護訪問。  1. 初始化:  在Linux下, 執行緒的互斥量資料型別是pthread_mutex_t. 在使用前, 要對它進行初始化:  對於靜態分配的互斥量, 可以把它設定為PTHREAD_MUTEX_INITIA

linux執行程式設計互斥

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <signal.h> #include <unistd.h> #include <pthread.h>

C/C++_執行程式設計_互斥

前言 定義/概念 問題的出現 在現代作業系統中,出現不止一個物件(程序/執行緒)對程式碼進行訪問是一個普遍的現象(併發的來源),這也就會出現對共享的資源(記憶體、硬體資源等)出現競爭佔有的狀態(競態)。資源是必須用於多個物件共享的,但是我們又不

C語言執行pthread庫-互斥

執行緒相關操作說明   一 pthread_t   pthread_t在標頭檔案/usr/include/bits/pthreadtypes.h中定義:   typedef unsigned long int pthread_t;   它是一個執行緒的識別符號。   二 pthread_create   函

C++ 執行併發控制——互斥 pthread_mutex

問題描述:有兩個執行緒,主執行緒負責接收資料,並暫時儲存在記憶體中,當記憶體中數量達到一定資料量時,批量提交到oracle中;另一個執行緒作為提交執行緒,定時檢查一遍,不論記憶體中資料量達到多少,定期將資料提交到oracle中。兩個執行緒併發進行,第一個寫入記憶體或者資料庫

C/C++執行執行同步(互斥與訊號量)

參考連結2.中寫的非常好,簡單易懂,上手快,非常好的博文。使用多執行緒及互斥鎖樣例:#include <iostream> #include <windows.h> using namespace std; HANDLE hMutex = NULL;

c/c++執行程式設計與無資料結構漫談

本文主要針對c/c++,系統主要針對linux。本文引述別人的資料均在引述段落加以宣告。 場景: thread...1...2...3...:多執行緒遍歷 thread...a...b...c...:多執行緒插入刪除修改 眾所周知的stl是多執行緒不安全的。為何stl不提供

檢視伺服器CPU的個數、CPU的數、執行

這裡有幾個概念: 1、一臺物理機的物理CPU的個數 2、一個CPU上的核數 3、一個核上面支援的執行緒數 有下面的計算公式: # 總核數 = 物理CPU個數 X 每顆物理CPU的核數  # 總邏輯CPU數 = 物理CPU個數 X 每顆物理CPU的核數 X 超執行緒數

執行程式設計——讀寫

一、什麼是讀寫鎖 讀寫鎖(也叫共享-獨佔鎖)實際是一種特殊的自旋鎖,它把對共享資源的訪問者劃分成讀者和寫者,讀者只對共享資源進行讀訪問,寫者則需要對共享資源進行寫操作。這種鎖相對於自旋鎖而言,能提高併發性,因為在多處理器系統中,它允許同時有多個讀者來訪問共享資源,最大可能的讀者數為實

java執行程式設計入門之的使用

package com.CUPK.lsz.TraditionalThread; //實現互斥的第一種方法:作為定義詞修飾程式碼 public class TraditonalThreadSynchronized1 { final Outputer outputer = new Outputer(

執行:利用互斥來處理全域性變數的互斥問題

多個執行緒會共享一些程序的靜態資料段的資源,比如在主執行緒中定義的全域性變數。肯定其他執行緒也能訪問的。 在Unix, Linux平臺下,我們利用互斥鎖來處理全域性變數的互斥問題。 考查互斥鎖變數,利用互斥鎖變數專門關聯一個變數。 資料型別: pthread_mutex_t

python執行程式設計(4): 死和可重入

線上程間共享多個資源的時候,如果兩個執行緒分別佔有一部分資源並且同時等待對方的資源,就會造成死鎖。儘管死鎖很少發生,但一旦發生就會造成應用的停止響應。下面看一個死鎖的例子: # encoding: UTF-8import threadingimport timec

物聯網海量裝置心跳註冊,脫網清除——執行高併發互斥落地

物聯網海量裝置心跳註冊,脫網清除——多執行緒高併發互斥鎖落地 目錄物聯網海量裝置心跳註冊,脫網清除——多執行緒高併發互斥鎖落地1.應用背景2.整體框架2.1.心跳註冊框架2.1.1.海量裝置2.1.2.心跳上報Handler流程2.2.脫網清理框架2.2.1.啟用字典表清理脫網裝置方法2.2.2.脫網清理流程

16.執行同步:互斥mutex

1.案例:兩個執行緒分別對一個變數,都++操作1000次 1.實際的執行結果:number的最終值<2000 2.資料混亂的原因: 多個執行緒操作了共享資源 CPU排程問題 3.解決:執行緒同步 int number=0;

執行同步:互斥,訊號量

同步概念: 當多個執行緒共享相同的一塊記憶體時(實際上在一個程序的各個執行緒之間,除了棧區的資料之外,其他的資料這幾個縣城之間都是相互共享的),需要確保每個執行緒看到一致的資料檢視。也就是說,這些執行緒在對資料進行操作時,應該是同步的,也就是說當一個執行緒正在操作一個數據時,其他執行緒無法同時對

Windows執行同步之互斥(Mutex)

執行緒同步的方式和機制臨界區、互斥區、事件、訊號量四種方式臨界區(Critical Section)、互斥量(Mutex)、訊號量(Semaphore)、事件(Event)的區別1、臨界區:通過對多執行緒的序列化來訪問公共資源或一段程式碼,速度快,適合控制資料訪問。在任意時刻

執行同步(互斥與訊號量的作用與區別)

“訊號量用在多執行緒多工同步的,一個執行緒完成了某一個動作就通過訊號量告訴別的執行緒,別的執行緒再進行某些動作(大家都在semtake的時候,就阻塞在 哪裡)。而互斥鎖是用在多執行緒多工互斥的,一個執行緒佔用了某一個資源,那麼別的執行緒就無法訪問,直到這個執行緒unloc

C++執行程式設計學習(1)】-CPU個數、CPU心數、CPU執行

轉自:CPU個數、CPU核心數、CPU執行緒數(by kimsimple)   CPU個數即CPU晶片個數。 CPU核心數是指物理上,也就是硬體上存在著幾個核心。比如,雙核就是包括2個相對獨立的CPU核心單元組,四核就包含4個相對獨立的CPU核心單元組。 CPU執行緒數是一

Java併發(十八):阻塞佇列BlockingQueue BlockingQueue(阻塞佇列)詳解 二叉堆(一)之 圖文解析 和 C語言的實現 多執行緒程式設計:阻塞、併發佇列的使用總結 Java併發程式設計:阻塞佇列 java阻塞佇列 BlockingQueue(阻塞佇列)詳解

阻塞佇列(BlockingQueue)是一個支援兩個附加操作的佇列。 這兩個附加的操作是:在佇列為空時,獲取元素的執行緒會等待佇列變為非空。當佇列滿時,儲存元素的執行緒會等待佇列可用。 阻塞佇列常用於生產者和消費者的場景,生產者是往佇列裡新增元素的執行緒,消費者是從佇列裡拿元素的執行緒。阻塞佇列就是生產者

C++使用thread類進行執行程式設計

C++11中引入了一個用於多執行緒操作的thread類,簡單多執行緒示例: #include <iostream> #include <thread> #include <Windows.h> using namespace std; void thread01(