3、Linux多線程,線程同步)3、Linux多線程,線程同步

來源:互聯網
上載者:User
3、Linux多線程,線程同步 

5)線程私人資料

    進程內的所有線程共用進程的資料空間,因此全域變數為所有線程所共有。但有時線程也需要儲存自己的私人資料,這時可以建立線程私人資料(Thread-specific Date)TSD來解決。線上程內部,私人資料可以被各個函數訪問,但對其他線程是屏蔽的。例如我們常見的變數errno,它返回標準的出錯資訊。它顯然不能是一個局部變數,幾乎每個函數都應該可以調用它;但它又不能是一個全域變數,否則在A線程裡輸出的很可能是B線程的出錯資訊。要實現諸如此類的變數,我們就必須使用線程資料。我們為每個線程資料建立一個鍵,它和這個鍵相關聯,在各個線程裡,都使用這個鍵來指代線程資料,但在不同的線程裡,這個鍵代表的資料是不同的,在同一個線程裡,它代表同樣的資料內容。

    線程私人資料採用了一鍵多值的技術,即一個鍵對應多個數值,訪問資料時好像是對同一個變數進行訪問,但其實是在訪問不同的資料。

    建立私人資料的函數有4個:pthread_key_create(建立), pthread_setspecific(設定), pthread_getspecific(擷取), pthread_key_delete(刪除)。

#include <pthread.h>

int pthread_key_creadte(pthread_key_t *key,void (*destr_fuction) (void *));

int pthread_setspecific(pthread_key_t key,const void * pointer));

void * pthread_getspecific(pthread_key_t key);

int pthread_key_delete(ptherad_key_t key);

6)線程同步

    線程的最大特點是資源的共用性,但資源共用中的同步問題是多線程編程的痛點。linux下提供了多種方式來處理線程同步,最常用的是互斥鎖、條件變數和非同步訊號。

1)互斥鎖(mutex)

    通過鎖機制實現線程間的同步。同一時刻只允許一個線程執行一個關鍵區段的代碼。

int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutex_attr_t *mutexattr);

int pthread_mutex_lock(pthread_mutex *mutex);

int pthread_mutex_destroy(pthread_mutex *mutex);

int pthread_mutex_unlock(pthread_mutex *

(1)先初始化鎖init()或靜態賦值pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIER

attr_t有:

PTHREAD_MUTEX_TIMED_NP:其餘線程等待隊列

PTHREAD_MUTEX_RECURSIVE_NP:嵌套鎖,允許線程多次加鎖,不同線程,解鎖後重新競爭

PTHREAD_MUTEX_ERRORCHECK_NP:檢錯,與一同,線程請求已用鎖,返回EDEADLK;

PTHREAD_MUTEX_ADAPTIVE_NP:適應鎖,解鎖後重新競爭

(2)加鎖,lock,trylock,lock阻塞等待鎖,trylock立即返回EBUSY

(3)解鎖,unlock需滿足是加鎖狀態,且由加鎖線程解鎖

(4)清除鎖,destroy(此時鎖必需unlock,否則返回EBUSY,//Linux下互斥鎖不佔用記憶體資源

範例程式碼

?
#include <cstdio>#include <cstdlib>#include <unistd.h>#include <pthread.h>#include "iostream" using namespace std; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;int tmp; void* thread(void *arg){    cout << "thread id is " << pthread_self() << endl;    pthread_mutex_lock(&mutex);    tmp = 12;    cout << "Now a is " << tmp << endl;    pthread_mutex_unlock(&mutex);    return NULL;    } int main(){    pthread_t id;    cout << "main thread id is " << pthread_self() << endl;    tmp = 3;    cout << "In main func tmp = " << tmp << endl;    if (!pthread_create(&id, NULL, thread, NULL))    {        cout << "Create thread success!" << endl;    }    else    {        cout << "Create thread failed!" << endl;    }    pthread_join(id, NULL);    pthread_mutex_destroy(&mutex);    return 0;}

 

編譯: g++ -o thread testthread.cpp -lpthread

說明:pthread庫不是Linux系統預設的庫,串連時需要使用靜態庫libpthread.a,所以在使用pthread_create()建立線程,以及調用pthread_atfork()函數建立fork處理常式時,需要連結該庫。在編譯中要加 -lpthread參數。

5)線程私人資料

    進程內的所有線程共用進程的資料空間,因此全域變數為所有線程所共有。但有時線程也需要儲存自己的私人資料,這時可以建立線程私人資料(Thread-specific Date)TSD來解決。線上程內部,私人資料可以被各個函數訪問,但對其他線程是屏蔽的。例如我們常見的變數errno,它返回標準的出錯資訊。它顯然不能是一個局部變數,幾乎每個函數都應該可以調用它;但它又不能是一個全域變數,否則在A線程裡輸出的很可能是B線程的出錯資訊。要實現諸如此類的變數,我們就必須使用線程資料。我們為每個線程資料建立一個鍵,它和這個鍵相關聯,在各個線程裡,都使用這個鍵來指代線程資料,但在不同的線程裡,這個鍵代表的資料是不同的,在同一個線程裡,它代表同樣的資料內容。

    線程私人資料採用了一鍵多值的技術,即一個鍵對應多個數值,訪問資料時好像是對同一個變數進行訪問,但其實是在訪問不同的資料。

    建立私人資料的函數有4個:pthread_key_create(建立), pthread_setspecific(設定), pthread_getspecific(擷取), pthread_key_delete(刪除)。

#include <pthread.h>

int pthread_key_creadte(pthread_key_t *key,void (*destr_fuction) (void *));

int pthread_setspecific(pthread_key_t key,const void * pointer));

void * pthread_getspecific(pthread_key_t key);

int pthread_key_delete(ptherad_key_t key);

6)線程同步

    線程的最大特點是資源的共用性,但資源共用中的同步問題是多線程編程的痛點。linux下提供了多種方式來處理線程同步,最常用的是互斥鎖、條件變數和非同步訊號。

1)互斥鎖(mutex)

    通過鎖機制實現線程間的同步。同一時刻只允許一個線程執行一個關鍵區段的代碼。

int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutex_attr_t *mutexattr);

int pthread_mutex_lock(pthread_mutex *mutex);

int pthread_mutex_destroy(pthread_mutex *mutex);

int pthread_mutex_unlock(pthread_mutex *

(1)先初始化鎖init()或靜態賦值pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIER

attr_t有:

PTHREAD_MUTEX_TIMED_NP:其餘線程等待隊列

PTHREAD_MUTEX_RECURSIVE_NP:嵌套鎖,允許線程多次加鎖,不同線程,解鎖後重新競爭

PTHREAD_MUTEX_ERRORCHECK_NP:檢錯,與一同,線程請求已用鎖,返回EDEADLK;

PTHREAD_MUTEX_ADAPTIVE_NP:適應鎖,解鎖後重新競爭

(2)加鎖,lock,trylock,lock阻塞等待鎖,trylock立即返回EBUSY

(3)解鎖,unlock需滿足是加鎖狀態,且由加鎖線程解鎖

(4)清除鎖,destroy(此時鎖必需unlock,否則返回EBUSY,//Linux下互斥鎖不佔用記憶體資源

範例程式碼

?
#include <cstdio>#include <cstdlib>#include <unistd.h>#include <pthread.h>#include "iostream" using namespace std; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;int tmp; void* thread(void *arg){    cout << "thread id is " << pthread_self() << endl;    pthread_mutex_lock(&mutex);    tmp = 12;    cout << "Now a is " << tmp << endl;    pthread_mutex_unlock(&mutex);    return NULL;    } int main(){    pthread_t id;    cout << "main thread id is " << pthread_self() << endl;    tmp = 3;    cout << "In main func tmp = " << tmp << endl;    if (!pthread_create(&id, NULL, thread, NULL))    {        cout << "Create thread success!" << endl;    }    else    {        cout << "Create thread failed!" << endl;    }    pthread_join(id, NULL);    pthread_mutex_destroy(&mutex);    return 0;}

 

編譯: g++ -o thread testthread.cpp -lpthread

說明:pthread庫不是Linux系統預設的庫,串連時需要使用靜態庫libpthread.a,所以在使用pthread_create()建立線程,以及調用pthread_atfork()函數建立fork處理常式時,需要連結該庫。在編譯中要加 -lpthread參數。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.