C語(yǔ)言線程對(duì)象和線程存儲(chǔ)的實(shí)現(xiàn)
當(dāng)每個(gè)線程為各自的變量使用全局標(biāo)識(shí)符時(shí),為保留這些變量各自的數(shù)據(jù),可以采用線程對(duì)象(thread-local object)和線程存儲(chǔ)(thread-specific storage)。
這兩項(xiàng)技術(shù)允許在一個(gè)給定線程中執(zhí)行的函數(shù)可以共享數(shù)據(jù)而不造成沖突,即便當(dāng)其他線程也在執(zhí)行同樣函數(shù)的情況下。
使用線程對(duì)象
線程對(duì)象是在聲明中包含新存儲(chǔ)類修飾符 _Thread_local 的全局或靜態(tài)對(duì)象。這意味著:每一個(gè)線程擁有屬于自己的線程對(duì)象實(shí)例,它在線程啟動(dòng)時(shí)創(chuàng)建并初始化。對(duì)象的存儲(chǔ)周期等于線程的運(yùn)行時(shí)間。在一個(gè)線程內(nèi)表達(dá)式里面的線程對(duì)象名,將引用這個(gè)對(duì)象在當(dāng)前線程下的本地實(shí)例。
修飾符 _Thread_local 可以與修飾符 static 或 extern 同時(shí)使用。頭文件 threads.h 定義了 thread_local 作為 _Thread_local 的同義詞。在例 1 中,主線程和新啟動(dòng)線程各自擁有線程本地變量 var 的一個(gè)實(shí)例。
【例1】使用一個(gè)線程對(duì)象
#include <stdio.h> #include <threads.h> thread_local int var = 10; void print_var(void){ printf("var = %d\n", var); } int func(void *); // 線程函數(shù) int main(int argc, char *argv[]) { thrd_t th1; if ( thrd_create( &th1, func, NULL ) != thrd_success ){ fprintf(stderr,"Error creating thread.\n"); return 0xff; } print_var(); // 輸出:var = 10 thrd_join(th1, NULL); return 0; } int func(void *arg) // 線程函數(shù) { var += 10; // 線程本地變量 print_var(); // 輸出:var = 20 return 0 }
使用線程存儲(chǔ)
線程存儲(chǔ)技術(shù)要比線程對(duì)象更加靈活。例如,獨(dú)立線程可以使用不同大小的內(nèi)存。它們可以動(dòng)態(tài)地分配內(nèi)存,并通過(guò)調(diào)用析構(gòu)函數(shù)再次釋放內(nèi)存。同時(shí),可以使用相同的標(biāo)識(shí)符訪問(wèn)這些獨(dú)立線程所在的不同內(nèi)存區(qū)域。
這種靈活性通過(guò)初始創(chuàng)建一個(gè)全局的鍵(key)實(shí)現(xiàn),該鍵表示了一個(gè)指向線程存儲(chǔ)的指針。然后,獨(dú)立線程通過(guò)指定其線程存儲(chǔ)的位置加載這個(gè)指針。該全局鍵值是類型為 tss_t 的對(duì)象。頭文件 threads.h 包含了該類型的定義以及 4 個(gè)用于管理線程存儲(chǔ)(簡(jiǎn)稱 TSS)函數(shù)的聲明:
int tss_create(tss_t*key,tss_dtor_t dtor);
通過(guò)析構(gòu)函數(shù) dtor 生成一個(gè)新的 TSS 指針,并且將 key 引用的對(duì)象設(shè)置為唯一標(biāo)識(shí)該 TSS 指針的值。類型 tss_dtor_t 是一個(gè)函數(shù)指針,定義為 void(*)(void*)(它指的是一個(gè)函數(shù)指針,該函數(shù)參數(shù)為 void 指針,并且該函數(shù)沒(méi)有返回值)。dtor 的返回值可以是一個(gè)空指針。
void tss_delete(tss_t key);
釋放 TSS 鍵 key 所使用的所有資源。
int tss_set(tss_t key,void*val);
對(duì)于調(diào)用 tss_set()的線程,將 key 所標(biāo)識(shí)的 TSS 指針設(shè)置為 val 所引用的內(nèi)存地址。
void*tss_get(tss_t key);
返回指向內(nèi)存塊的指針,該內(nèi)存塊為正在調(diào)用的線程通過(guò)函數(shù) tss_set()設(shè)置。如果發(fā)生錯(cuò)誤,tss_get()返回 NULL。
如果函數(shù) tss_create()和 tss_set()發(fā)生錯(cuò)誤,則返回 thrd_error;否則,返回 thrd_success。
例 2 中的程序在動(dòng)態(tài)分配的線程存儲(chǔ)中,保留線程的名稱。
【例2】使用線程存儲(chǔ)
#include <threads.h> #include <stdio.h> #include <stdlib.h> #include <string.h> tss_t key; // 用于TSS指針的全局鍵 int thFunc(void *arg); // 線程函數(shù) void destructor(void *data); // 析構(gòu)函數(shù) int main(void) { thrd_t th1, th2; int result1 = 0, result2 = 0; // 創(chuàng)建一個(gè)TSS密鑰 if (tss_create(&key, destructor) != thrd_success) return -1; // 創(chuàng)建線程 if (thrd_create(&th1, thFunc, "Thread_1") != thrd_success || thrd_create(&th2, thFunc, "Thread_2") != thrd_success) return -2; thrd_join(th1, &result1); thrd_join(th2, &result2); if ( result1 != 0 || result2 != 0 ) fputs("Thread error\n", stderr); else puts("Threads finished without error."); tss_delete(key); // 釋放TSS指針?biāo)械馁Y源 return 0; } void print(void) // 顯示線程存儲(chǔ) { printf( "print: %s\n", (char*)tss_get(key) ); } int thFunc( void *arg ) { char *name = (char*)arg; size_t size = strlen(name)+1; // 設(shè)置線程存儲(chǔ) if ( tss_set(key, malloc(size)) != thrd_success ) return -1; // 存儲(chǔ)數(shù)據(jù) strcpy((char*)tss_get(key), name); print(); return 0; } void destructor(void *data) { printf("Destructor for %s\n", (char*)data); free(data); // 釋放內(nèi)存 }
到此這篇關(guān)于C語(yǔ)言線程對(duì)象和線程存儲(chǔ)的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)C語(yǔ)言線程對(duì)象和線程存儲(chǔ)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于QT實(shí)現(xiàn)自定義溫度計(jì)的示例代碼
QT原生控件沒(méi)有實(shí)現(xiàn)如儀表盤或者溫度計(jì)的控件,只好自己實(shí)現(xiàn),所以本文為大家介紹了如何利用qt實(shí)現(xiàn)自定義溫度/濕度控件,感興趣的小伙伴可以了解下2023-11-11C++應(yīng)用實(shí)現(xiàn)簡(jiǎn)易五子棋游戲
這篇文章主要為大家詳細(xì)介紹了C++應(yīng)用實(shí)現(xiàn)簡(jiǎn)易五子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05Qt中圖片旋轉(zhuǎn)縮放操作的實(shí)現(xiàn)
本文主要介紹了Qt中圖片旋轉(zhuǎn)縮放操作的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-01-01