1. 程式人生 > >Linux下c++多執行緒和互斥鎖

Linux下c++多執行緒和互斥鎖

一、多執行緒
多執行緒使用的是pthread庫,寫程式的時候需要引入標頭檔案pthread.h, g++編譯的時候需要加上該庫的依賴“-lpthread”。
1 先看程式便於理解,程式碼下面有對註釋的解釋。下面的程式碼含義是建立兩個執行緒,一個執行緒去計算某個變數的階乘,另一個去計算從0到某個變數的和

#include <iostream>
#include <pthread.h>
#include <string.h>
void *thread1_fact(void *arg);  // 註釋1
void *thread2_sum(void *arg);
int
main() { pthread_t t_fact; // 註釋2 pthread_t t_sum; int i = 10; if (pthread_create(&t_fact, NULL, thread1_fact, &i) != 0) {  // 註釋3 std::cout << "pthread_create() error"; return -1; } if (pthread_create(&t_sum, NULL, thread2_sum, &i) != 0) { std
::cout << "pthread_create() error"; return -1; } pthread_join(t_fact, NULL);  // 註釋4 pthread_join(t_sum, NULL); return 0; } void *thread1_fact(void *arg) { int i = *(int*)arg; //註釋5 int fact = 1; while(i){ fact *= i; i--; } std::cout << "thread1 get fact:"
<< fact << std::endl; } void *thread2_sum(void *arg) { int i = *(int*)arg; int sum = 0; while (i>0) { sum += i; i--; } std::cout << "thread2 get sum:" << sum << std::endl; }

輸出:
thread1 get fact:3628800
thread2 get sum:55

2 對上面的函式的解析
註釋1
首先宣告函式,該函式是建立的執行緒要執行的函式,注意裡面的引數,是無型別的指標
註釋2
執行緒要根據執行緒ID區分,改變數用於儲存執行緒的ID
註釋3:
pthread_create()原型:
extern int pthread_create (pthread_t *__restrict __newthread,
const pthread_attr_t *__restrict __attr,
void (*__start_routine) (void ),
void *__restrict __arg) __THROWNL __nonnull ((1, 3));

包含四個引數如下
__newthread: 如果建立成功,改變數儲存建立成功的執行緒ID
__attr: 傳遞執行緒屬性引數,傳遞NULL時建立預設屬性的執行緒
__start_routine: 相當於執行緒的main函式,建立好的執行緒執行該函式
__arg: 要傳遞給執行緒執行函式的引數,它其實是一個變數的地址,不傳遞引數時可以設定為NULL
該函式如果執行成功,則返回0,執行失敗返回其他值
註釋4
大家可以先把這行程式碼去掉看看效果,會發現可能沒有任何輸出,這並不是錯誤。這是由於main函式執行完畢即可結束,沒有等待我們建立的執行緒結束。所以pthread_join(t_fact, NULL);的含義就是等待t_fact這個執行緒結束後,main函式才會結束。
註釋5
如上面所說,傳遞過來的引數是一個無型別的指標,我們需要將其轉換為我們需要的資料。

二、互斥鎖
涉及到多執行緒必然會有互斥問題,上面的程式碼沒有訪問衝突,但是加入有兩個執行緒一個將其增1,一個將其減1,這樣如果沒有互斥訪問就可能存在錯誤。同上,先上程式碼便於理解,註釋會在下文給出。
1 下面的程式碼含義是兩個程序對某個bool變數互斥訪問,此處不再解釋多執行緒的問題,只解釋互斥鎖的寫法

#include <iostream>
#include <netinet/in.h>
#include <pthread.h>

void *thread_write(void *arg);

pthread_mutex_t mutex;  // 註釋1

int main() {
    pthread_mutex_init(&mutex, NULL);  //註釋2
    pthread_t t_1;
    pthread_t t_2;
    if (pthread_create(&t_1, NULL, thread_write, NULL) != 0) {
        std::cout << "pthread_create() error";
        return -1;
    }
    if (pthread_create(&t_2, NULL, thread_write, NULL) != 0) {
        std::cout << "pthread_create() error";
        return -1;
    }
    pthread_join(t_1, NULL);
    pthread_join(t_2, NULL);
    pthread_mutex_destroy(&mutex); //註釋3
    return 0;
}

void *thread_write(void *arg) {
    pthread_mutex_lock(&mutex);  //註釋4
    std::cout << "one apply for the mutex successfully" << std::endl;
    pthread_mutex_unlock(&mutex);  //註釋5
}

2 對上面註釋的解釋
註釋1
定義一個互斥變數
註釋2
將互斥變數初始化
註釋3
結束後將互斥量銷燬
註釋4
申請該互斥鎖,申請到的話可以執行下面的程式碼,申請失敗則會阻塞,只能有一個執行緒可以申請到。
註釋5
執行緒結束訪問後釋放互斥鎖,可以讓其他執行緒申請該鎖。

補充:上面兩個只是簡單的介紹,還有其他原理和其他用法由於本人水平所限沒有介紹,後期再慢慢更新,如有錯誤或者建議可以留言。