導航:首頁 > 操作系統 > linux線程共享內存

linux線程共享內存

發布時間:2024-04-02 21:39:19

1. linux共享內存的分配

進程通過調用shmget(Shared Memory GET,獲取共享內存)來分配一個共享內存塊。
該函數的第一個參數是一個用來標識共享內存塊的鍵值。彼此無關的進程可以通過指定同一個鍵以獲取對同一個共享內存塊的訪問。不幸的是,其它程序也可能挑選了同樣的特定值作為自己分配共享內存的鍵值,從而產生沖突。用特殊常量IPC_PRIVATE作為鍵值可以保證系統建立一個全新的共享內存塊。
該函數的第二個參數指定了所申請的內存塊的大小。因為這些內存塊是以頁面為單位進行分配的,實際分配的內存塊大小將被擴大到頁面大小的整數倍。
第三個參數是一組標志,通過特定常量的按位或操作來shmget。這些特定常量包括:
IPC_CREAT:這個標志表示應創建一個新的共享內存塊。通過指定這個標志,我們可以創建一個具有指定鍵值的新共享內存塊。
IPC_EXCL:這個標志只能與 IPC_CREAT 同時使用。當指定這個標志的時候,如果已有一個具有這個鍵值的共享內存塊存在,則shmget會調用失敗。也就是說,這個標志將使線程獲得一個「獨有」的共享內存塊。如果沒有指定這個標志而系統中存在一個具有相同鍵值的共享內存塊,shmget會返回這個已經建立的共享內存塊,而不是重新創建一個。
模式標志:這個值由9個位組成,分別表示屬主、屬組和其它用戶對該內存塊的訪問許可權。其中表示執行許可權的位將被忽略。指明訪問許可權的一個簡單辦法是利用<sys/stat.h>中指定,並且在手冊頁第二節stat條目中說明了的常量指定。例如,S_IRUSR和S_IWUSR分別指定了該內存塊屬主的讀寫許可權,而 S_IROTH和S_IWOTH則指定了其它用戶的讀寫許可權。 下面例子中shmget函數創建了一個新的共享內存塊(當shm_key已被佔用時則獲取對一個已經存在共享內存塊的訪問),且只有屬主對該內存塊具有讀寫許可權,其它用戶不可讀寫。
int segment_id = shmget (shm_key, getpagesize (), IPC_CREAT | S_IRUSR| S_IWUSR ); 如果調用成功,shmget將返回一個共享內存標識符。如果該共享內存塊已經存在,系統會檢查訪問許可權,同時會檢查該內存塊是否被標記為等待摧毀狀態。

2. linux裡面,進程與線程到底有什麼本質的區別

線程:是進程中執行的一條路徑,是系統調度的最小單位。

進程:是正在運行的程序,是系統分配資源的最小單位。

線程與進程關系

1.一個進程可以有多個線程,一個線程只能屬於一個進程。

2.同一個進程下的所有線程共享該進程下的所有資源。

3.真正在處理機上運行的是線程,不是進程,線程是進程內的一個執行單元,是進程內的可調度實體。

Linux線程與進程區別

進程:

優點:多進程可以同時利用多個CPU,能夠同時進行多個操作。

缺點:耗費資源(創建一個進程重新開辟內存空間)。

進程不是越多越好,一般進程個數等於cpu個數。

線程:

優點:共享內存,尤其是進行IO操作(網路、磁碟)的時候(IO操作很少用cpu),可以使用多線程執行並發操作。

缺點:搶占資源。

3. Linux綰跨▼鍜岃繘紼媗inux鐨勭嚎紼嬪拰榪涚▼

linuxtop鏌ョ湅鐨勬槸榪涚▼榪樻槸綰跨▼錛

top鍛戒護姣忎竴琛屾樉紺虹殑鏄涓涓榪涚▼錛屽姞涓-H(Threadstoggle)鐨勫悗緙鏄劇ず鐨勬墠鏄綰跨▼銆

linux綰跨▼鍏變韓鍜岃繘紼嬪唴瀛樼殑鍏崇郴錛

鍖哄埆鍜岃仈緋伙細

1銆佽繘紼嬫槸鐙絝嬭繍琛岀殑瀹炰綋錛屾湁鐙絝嬬殑璧勬簮鍒嗛厤錛

2銆佸悓涓榪涚▼鐨勭嚎紼嬩箣闂村叡浜榪涚▼鐨勮祫婧愶紱

3銆佹墍鏈夌殑榪涚▼鑷沖皯鏈変竴涓鎵ц岀嚎紼嬶紱

4銆佺嚎紼嬬殑鍒涘緩鍜屽垏鎹浠d環姣旇繘紼嬬殑灝忥紱綰跨▼闂寸殑閫氫俊鏂規硶錛1銆佸悓涓榪涚▼鐨勭嚎紼嬩箣闂撮氫俊鐨勬渶綆鍗曞姙娉曞氨鏄浣跨敤鍏ㄥ矓鍙橀噺錛2銆佷笉鍚岃繘紼嬬殑綰跨▼涔嬮棿閫氫俊闇瑕侀氳繃涓嬮潰榪涚▼闂寸殑閫氫俊鏉ュ疄鐜幫紱榪涚▼闂寸殑閫氫俊鏂規硶錛1銆佺¢亾2銆佷俊鍙烽噺3銆佸叡浜鍐呭瓨4銆佹秷鎮闃熷垪5銆佸楁帴瀛

linux鎬庝箞鎸囧畾綰跨▼搴擄紵

澶ф傜殑浠嬬粛涓涓婰inux鐨勬寚瀹欳PU榪愯岋紝鍖呮嫭榪涚▼鍜岀嚎紼嬨俵inux涓嬬殑top鍛戒護鏄鍙浠ユ煡鐪嬪綋鍓嶇殑cpu鐨勮繍琛岀姸鎬侊紝鎸1鍙浠ユ煡鐪嬬郴緇熸湁澶氬皯涓狢PU錛屼互鍙婃瘡涓狢PU鐨勮繍琛岀姸鎬併傚彲鏄濡備綍鏌ョ湅綰跨▼鐨凜PU鍛錛

top-Hppid,pid灝辨槸浣犲綋鍓嶇▼搴忕殑榪涚▼鍙鳳紝濡傛灉鏄澶氱嚎紼嬬殑璇濓紝鏄鍙浠ユ煡鐪嬭繘紼嬪唴鎵鏈夌嚎紼嬬殑CPU鍜屽唴瀛樹嬌鐢ㄦ儏鍐點

pstree鍙浠ユ煡鐪嬩富嬈$嚎紼嬶紝鍚屾牱鐨刾stree-ppid銆傚彲浠ユ煡鐪嬭繘紼嬬殑綰跨▼鎯呭喌銆

taskset榪欎釜鍏跺疄鎵嶆槸閲嶇偣錛屽彲浠ユ煡鐪嬩互鍙婅劇疆褰撳墠榪涚▼鎴栫嚎紼嬭繍琛岀殑CPU(璁劇疆浜插拰鍔)銆

taskset-pcpid,鏌ョ湅褰撳墠榪涚▼鐨刢pu錛屽綋鐒舵湁鐨勬椂鍊欎笉鍙鏄涓涓錛宼askset-pccpu_numpid,cpu_num灝辨槸璁劇疆鐨刢pu銆傝繖鏍風殑璇濆熀鏈鐨勫懡浠ゅ拰鎿嶄綔鍏跺疄澶у墮兘鐭ラ亾浜嗭紝鎺ヤ笅鏉ュ氨鏄鍦ㄤ唬鐮佷腑瀹屾垚榪欎簺鎿嶄綔錛屽苟閫氳繃鍛戒護鍘婚獙璇佷唬鐮佺殑鎴愬姛鐜囥傝繘紼嬪埗瀹欳PU榪愯岋細

viewplain#include#include#include#include#include#define__USE_GNU#include#include#includeintmain(intargc,char*argv){//sysconf鑾峰彇鏈夊嚑涓狢PUintnum=sysconf(_SC_NPROCESSORS_CONF);intcreated_thread=0;intmyid;inti;intj=0;//鍘熺悊鍏跺疄寰堢畝鍗曪紝灝辨槸閫氳繃cpu_set_t榪涜屼綅涓庢搷浣渃pu_set_tmask;cpu_set_tget;if(argc!=2){printf(usage:./cpunumn);exit(1);}myid=atoi(argv)

;printf(systemhas%iprocessor(s).n,num)

;//鍏堣繘琛屾竻絀猴紝鐒跺悗璁劇疆鎺╃爜CPU_ZERO(mask);CPU_SET(myid,mask)

;//璁劇疆榪涚▼鐨勪翰鍜屽姏if(sched_setaffinity(0,sizeof(mask),mask)==-1){printf(warning:couldnotsetCPUaffinity,continuing...n);}while(1){CPU_ZERO(get);//鑾峰彇褰撳墠榪涚▼鐨勪翰鍜屽姏if(sched_getaffinity(0,sizeof(get),get)==-1){printf(warning:coundnotgetcpuaffinity,continuing...n);}for(i=0;inum;i++){if(CPU_ISSET(i,get)){printf(thisprocess%disrunningprocessor:%dn,getpid(),i);}}}return0;}榪涚▼璁劇疆CPU榪愯岋紝鍏跺疄鍙鑳芥槸鍗曠嚎紼嬨傚氱嚎紼嬭懼畾CPU濡備笅錛

viewplain#define_GNU_SOURCE#include#include#include#include#include#includevoid*myfun(void*arg){cpu_set_tmask;cpu_set_tget;charbuf;inti;intj;//鍚屾牱鐨勫厛鍘昏幏鍙朇PU鐨勪釜鏁癷ntnum=sysconf(_SC_NPROCESSORS_CONF);printf(systemhas%dprocessor(s)n,num);for(i=0;inum;i++){CPU_ZERO(mask);CPU_SET(i,mask);//榪欎釜鍏跺疄鍜岃劇疆榪涚▼鐨勪翰鍜屽姏鍩烘湰鏄涓鏍風殑if(pthread_setaffinity_np(pthread_self(),sizeof(mask),mask)0){fprintf(stderr,setthreadaffinityfailedn);}CPU_ZERO(get);if(pthread_getaffinity_np(pthread_self(),sizeof(get),get)0){fprintf(stderr,getthreadaffinityfailedn);}for(j=0;jnum;j++){if(CPU_ISSET(j,get)){printf(thread%disrunninginprocessor%dn,(int)pthread_self(),j);}}j=0;while(j++100000000){memset(buf,0,sizeof(buf));}}pthread_exit(NULL);}intmain(intargc,char*argv){pthread_ttid;if(pthread_create(tid,NULL,(void*)myfun,NULL)!=0){fprintf(stderr,threadcreatefailedn);return-1;}pthread_join(tid,NULL);return0;}

linux涓鐨勭嚎紼嬫湁鍝鍑犵嶇姸鎬侊紵

灝辯華錛氱嚎紼嬪垎閰嶄簡CPU浠ュ栫殑鍏ㄩ儴璧勬簮錛岀瓑寰呰幏寰桟PU璋冨害鎵ц岋細綰跨▼鑾峰緱CPU錛屾e湪鎵ц岄樆濉烇細綰跨▼鐢變簬鍙戠敓I/O鎴栬呭叾浠栫殑鎿嶄綔瀵艱嚧鏃犳硶緇х畫鎵ц岋紝灝辨斁寮冨勭悊鏈猴紝杞鍏ョ嚎紼嬪氨緇闃熷垪鎸傝搗錛氱敱浜庣粓絝璇鋒眰錛屾搷浣滅郴緇熺殑瑕佹眰絳夊師鍥狅紝瀵艱嚧鎸傝搗銆

linux鍐呮牳涓錛屽伐浣滈槦鍒楀拰綰跨▼鏈変粈涔堝尯鍒錛

workqueue鏄涓縐峛ottomhalf錛屼腑鏂澶勭悊鐨勫悗鍗婄▼錛屽己璋冪殑鏄鍔ㄦ佺殑姒傚康錛屽嵆work鏄閲嶇偣錛岃宷ueue鏄鍏舵°

waitqueue鏄涓縐嶃屼換鍔¢槦鍒椼嶏紝鍙浠ユ妸涓浜涜繘紼嬫斁鍦ㄤ笂闈㈢潯鐪犵瓑寰呮煇涓浜嬩歡錛屽己璋冮潤鎬佸氫竴浜涳紝閲嶇偣鍦╭ueue涓婏紝鍗沖畠灝辨槸涓涓猶ueue錛岃繖涓猶ueue濡備綍璋冨害錛屼粈涔堟椂鍊欒皟搴﹀苟涓嶉噸瑕佺瓑寰呴槦鍒楀湪鍐呮牳涓鏈夊緢澶氱敤閫旓紝灝ゅ叾閫傚悎鐢ㄤ簬涓鏂澶勭悊錛岃繘紼嬪悓姝ュ強瀹氭椂銆傝繖閲屽彧璇達紝榪涚▼緇忓父蹇呴』絳夊緟鏌愪簺浜嬩歡鐨勫彂鐢熴備緥濡傦紝絳夊緟涓涓紓佺洏鎿嶄綔鐨勭粓姝錛岀瓑寰呴噴鏀劇郴緇熻祫婧愶紝鎴栬呯瓑寰呮椂闂寸粡榪囧滻瀹氱殑闂撮殧銆傜瓑寰呴槦鍒楀疄鐜頒簡鍦ㄤ簨浠朵笂鐨勬潯浠剁瓑寰咃紝甯屾湜絳夊緟鐗瑰畾浜嬩歡鐨勮繘紼嬫妸鏀捐繘鍚堥傜殑絳夊緟闃熷垪錛屽苟鏀懼純鎺у埗鏉冦傚洜姝ゃ傜瓑寰呴槦鍒楄〃紺轟竴緇勭潯鐪犵殑榪涚▼錛屽綋鏌愪竴鏉′歡涓虹湡鏃訛紝鐢卞唴鏍稿敜閱掕繘紼嬨傜瓑寰呴槦鍒楃敱寰鐜閾捐〃瀹炵幇錛屽叾鍏冪礌鍖呮嫭鎸囧悜榪涚▼鎻忚堪絎︾殑鎸囬拡銆傛瘡涓絳夊緟闃熷垪閮芥湁涓涓絳夊緟闃熷垪澶達紝絳夊緟闃熷垪澶存槸涓涓綾誨瀷涓簑ait_queue_head_t鐨勬暟鎹緇撴瀯銆傜瓑寰呴槦鍒楅摼琛ㄧ殑姣忎釜鍏冪礌浠h〃涓涓鐫$湢榪涚▼錛岃ヨ繘紼嬬瓑寰呮煇涓浜嬩歡鐨勫彂鐢燂紝鎻忚堪絎﹀湴鍧瀛樻斁鍦╰ask瀛楁典腑銆傜劧鑰岋紝瑕佸敜閱掔瓑寰呴槦鍒椾腑鎵鏈夌殑榪涚▼鏈夋椂騫朵笉鏂逛究銆備緥濡傦紝濡傛灉涓や釜鎴栧氫釜榪涚▼鍦ㄧ瓑寰呬簰鏂ヨ塊棶鏌愪竴涓瑕侀噴鏀劇殑璧勬簮錛屼粎鍞ら啋絳夊緟闃熷垪涓涓涓鎵嶆湁鎰忎箟銆傝繖涓榪涚▼鍗犳湁璧勬簮錛岃屽叾浠栬繘紼嬬戶緇鐫$湢鍙浠ョ敤DECLARE_WAIT_QUEUE_HEAD(name)瀹忓畾涔変竴涓鏂扮殑絳夊緟闃熷垪錛岃ュ畯闈欐佸湴澹版槑鍜屽垵濮嬪寲鍚嶄負name鐨勭瓑寰呴槦鍒楀ご鍙橀噺銆俰nit_waitqueue_head()鍑芥暟鐢ㄤ簬鍒濆嬪寲宸插姩鎬佸垎閰嶇殑waitqueuehead鍙橀噺絳夊緟闃熷垪鍙浠ラ氳繃DECLARE_WAITQUEUE()闈欐佸壋寤猴紝涔熷彲浠ョ敤init_waitqueue_head()鍔ㄦ佸壋寤恆傝繘紼嬫斁鍏ョ瓑寰呴槦鍒楀苟璁劇疆鎴愪笉鍙鎵ц岀姸鎬併傚伐浣滈槦鍒楋紝workqueue錛屽畠鍏佽稿唴鏍鎬唬鐮佹潵璇鋒眰鍦ㄥ皢鏉ユ煇涓鏃墮棿璋冪敤涓涓鍑芥暟銆傜敤鏉ュ勭悊涓嶆槸寰堢揣鎬ヤ簨浠剁殑鍥炶皟鏂瑰紡澶勭悊鏂規硶.宸ヤ綔闃熷垪鐨勪綔鐢ㄥ氨鏄鎶婂伐浣滄帹鍚,浜ょ敱涓涓鍐呮牳綰跨▼鍘繪墽琛岋紝鏇寸洿鎺ョ殑璇村氨鏄鍐欎簡涓涓鍑芥暟,鑰岀幇鍦ㄤ笉鎯抽┈涓婃墽琛屽畠錛岄渶瑕佸湪灝嗘潵鏌愪釜鏃跺埢鍘繪墽琛岋紝閭e氨寰楃敤宸ヤ綔闃熷垪鍑嗘病閿欍傚傛灉闇瑕佺敤涓涓鍙浠ラ噸鏂拌皟搴︾殑瀹炰綋鏉ユ墽琛屼笅鍗婇儴澶勭悊錛屼篃搴旇ヤ嬌鐢ㄥ伐浣滈槦鍒椼傛槸鍞涓鑳藉湪榪涚▼涓婁笅鏂囪繍琛岀殑涓嬪崐閮ㄥ疄鐜扮殑鏈哄埗銆傝繖鎰忓懗鐫鍦ㄩ渶瑕佽幏寰楀ぇ閲忕殑鍐呭瓨鏃躲佸湪闇瑕佽幏鍙栦俊鍙烽噺鏃訛紝鍦ㄩ渶瑕佹墽琛岄樆濉炲紡鐨処/O鎿嶄綔鏃訛紝閮戒細闈炲父鏈夌敤銆

4. linux系統下進程通信的6種方式分別是什麼它們的區別在什麼地方線程通信有幾種方式這是很多人的疑問

管道:管道是一種半雙工的通信方式,數據只能單向流動,而且只能在具有親緣關系的進程間使用。進程的親緣關系通常是指父子進程關系。

信號量 :信號量是一個計數器,可以用來控制多個進程對共享資源的訪問。它常作為一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。因此,主要作為進程間以及同一進程內不同線程之間的同步手段。

消息隊列:消息隊列是由消息的鏈表,存放在內核中並由消息隊列標識符標識。消息隊列克服了信號傳遞信息少、管道只能承載無格式位元組流以及緩沖區大小受限等缺點。

信號 :
信號是一種比較復雜的通信方式,用於通知接收進程某個事件已經發生。
共享內存:共享內存就是映射一段能被其他進程所訪問的內存,這段共享內由一個進程創建,多個進程都可以訪問。共享內存是最快的IPC 方式,
它是針對其他進程間通信方式運行效率低而專門設計的。它往往與其他通信機制,如信號量,合使用,來實現進程間的同步和通信。

套接字: 套解口也是一種進程間通信機制,與其他通信機制不同的是,它可用於不同及其間的進程通信

管道可以用於shell重定向,也就是命令管道類似grep
命名管道可以實現通信,通過makefifo傳遞消息
消息隊列也可以實現通信,不過相比命名管道有消息過濾的好處
信號其實就是KILL的應用
信號量是對臨界共享資源的合理調度
共享內存, 就是字面意思共享的內存

而線程通信方式有:互斥鎖,條件變數,讀寫鎖

5. 有人能教下我有關linux裡面線程的知識嗎

.線程的基本介紹
(1)線程的概述
線程與進程類似,也允許應用程序並發執行多個任務的一種機制。一個進程可以包含多個線程,同一程序中的所有線程共享同一份全局內存區域,線程之間沒有真正意義的等級之分。同一個進程中的線程可以並發執行,如果處理器是多核的話線程也可以並行執行,如果一個線程因為等待I/O操作而阻塞,那麼其他線程依然可以繼續運行
(2)線程優於進程的方面

argv,environ

主線程棧
線程3的棧
線程2的棧
線程1的棧
共享函數庫共享的內存

未初始化的數據段
初始化數據段
文本
.進程間的信息難以共享。由於除去只讀代碼段外,父子進程並未共享內存,因此必須採用一些進程間通訊,在進程之間交換信息
.調用fork()來創建進程代價相對較高
線程很好的解決了上述倆個問題
.線程之間能夠方便,快速的共享信息,只需將數據復制到共享(全局或堆)變數中即可
.創建線程比創建線程通常要快10甚至更多,線程創建之所以快,是因為fork創建進程時所需復制多個屬性,而在線程中,這些屬性是共享的。
(3)創建線程
啟動程序時,產生的進程只有單條線程,我們稱之為主線程
#include<pthread.h>
int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void*(*start)(void *),void *arg);12

新線程通過調用帶有arg的函數開始執行,調用pthread_create()的線程會繼續執行該調用之後的語句。
(4)終止線程
可以以如下方式終止線程的運行
.線程調用pthread_exit()
.線程start函數執行return語句並返回指定值
.調用pthread_cancel()取消線程
.任意線程調用了exit(),或者主線程執行了return語句,都會導致進程中的所有線程立即終止
pthread_exit()函數可以終止線程,且其返回值可由另一線程通過調用pthread_join()獲得
#include<pthread.h>void pthread_exit(void *retval);12

調用pthread_exit()相當於在線程的start函數中執行return,不同之處在於,pthread_exit()可以在任何地方調用,參數retval指定了線程的返回值
(5)獲取線程ID
#include<pthread.h>pthread_t pthread_self(void);12

線程ID在應用程序中主要有如下用途
.不同的pthreads函數利用線程ID來標識要操作目標線程。
.在具體的應用程序中,以特定線程的線程ID作為動態數據結構的標簽,這頗有用處,既可用來識別某個數據結構的創建者或屬主線程,又可確定隨後對該數據結構執行操作的具體線程
函數pthread_equal()可檢查倆個線程的ID是否相同
#include<pthread.h>int pthread_equal(pthread_t t1,pthread_t t2);//如果相同返回非0值,否則返回0123

(6)連接已終止的線程
函數pthread_join()等待由thread表識的線程終止
#include<pthread.h>int pthread_join(pthread_t thread,void **retval);//返回0調用成功,否則失敗123

如果pthread_join()傳入一個之前已然連接過的線程ID,將會導致無法預知的行為,當相同線程ID在參與一次連接後恰好為另一新建線程所重用,再度連接的可能就是這個新線程
若線程未分離,則就應該使用pthread_join()來連接線程,否則會產生僵屍線程
pthrea_join()函數的要點
.線程之間的關系是對等的,所以任意線程都可以調用pthread_join()來連接其他線程
.pthread_join()無法針對任意線程,只能連接單個線程
(6)線程的分離
默認情況下線程都是可連接的,但有時候,我們並不關心線程退出的狀態,我們可以調用pthread_detach()並向thread參數傳入指定線程的的標識符,將該線程標記為處於分離狀態
#include<pthread.h>int pthread_detach(pthread_t thread);//返回0成功,否則失敗123

一旦線程處於分離狀態,就不能在使用pthread_join()來獲取其狀態,也無法使其重返可連接狀態
(7)在應用程序中如何來選擇進程還是線程
.線程之間共享數據很簡單,進程間的數據共享需要更多的投入
.創建線程要比創建進程塊很多
.多線程編程時,需要確保調用線程安全的函數
.某個線程中的bug可能會危害進程中所有線程
.每個線程都在徵用宿主進程中有限的虛擬地址空間
.在多線程應用中,需要小心使用信號
.除了數據,線程還可以共享文件描述符,信號處置,當前工作目錄,以及用戶ID和組ID
線程的同步
(1)保護共享變數訪問:互斥量
線程的主要優勢在於能夠通過全局變數來共享信息,不過這種共享是有代價的。必須確保多個線程修改同一變數時,不會有其他線程也正在修改此變數,為避免線程更新時共享變數時所出現的問題,必須使用互斥量來確保同時僅有一個線程可以訪問某項共享資源
(2)靜態分配的互斥鎖
互斥鎖既可以像靜態變數那樣分配,也可以在運行時動態分配,互斥量屬於pthread_mutex_t類型的變數,在使用之前必須對其初始化。對於靜態分配的互斥量而言,可如下例所示,將PTHREAD_MUTEX_INITIALIZER賦給互斥量
pthread_mutex_t = PTHREAD_MUTEX_INITIALIZER;1

1.加鎖和解鎖互斥量
初始化之後,互斥量處於未鎖定狀態。函數pthread_mutex_lock()可以鎖定某一互斥量
而函數pthread_mutex_unlock()則可以將一個互斥量解鎖
#include<pthread.h>int pthread_mutex_lock(pthread_mutex_t *mutex);int pthread_mutex_unlock(pthread_mutex_t *mutex);//返回0成功,其他失敗1234

要鎖定互斥量,在調用pthread_mutex_lock()時需要指定互斥量,如果互斥量當前處於未鎖定狀態,則該調用將會立即返回,如果該互斥量已被其他線程鎖定,那麼該調用將會阻塞,直至互斥量被解鎖
函數pthread_mutex_unlock()將解鎖之前已遭調用線程鎖定的互斥量
2.互斥量的性能
通常情況下,線程會花費更多的時間去做其他工作,對互斥量的加鎖解鎖相對要少的多,因此使用互斥量對大部分程序來說性能並無顯著的影響
3.互斥量的死鎖
當一個線程需要同時訪問多個共享資源時,沒個資源由不同的互斥索管理。當超過一個線程加鎖同一組互斥量時,就有可能發生死鎖。如下圖所示
線程A
1.pthread_mutex_lock(mutex1);
2.pthread_mutex_lock(mutex2);
線程2
1.pthread_mutex_lock(mutex2);
2.pthread_mutex_lock(mutex1);
每個線程都成功的鎖住一個互斥量,接著試圖對以為另一線程鎖定的互斥量加鎖,就會一直等下去
要避免此類死鎖問題,最簡單的就是定義互斥量的層級關系

6. Linux線程及同步

linux多線程
1.線程概述
線程是一個進程內的基本調度單位,也可以稱為輕量級進程。線程是在共享內存空間中並發的多道執行路徑,它們共享一個進程的資源,如文件描述和信號處理。因此,大大減少了上下文切換的開銷。一個進程可以有多個線程,也就
是有多個線程式控制製表及堆棧寄存器,但卻共享一個用戶地址空間。
2.線程實現
線程創建pthread_create()
所需頭文件#include
<pthread.h>
函數原型int
pthread_create
((pthread_t
*thread,
pthread_attr_t
*attr,
thread:線程標識符
attr:線程屬性設置
start_routine:線程函數的起始地址
arg:傳遞給start_routine的參數
函數返回值
成功:0
出錯:-1
線程退出pthread_exit();
所需頭文件#include
<pthread.h>
函數原型void
pthread_exit(void
*retval)
函數傳入值retval:pthread_exit()調用者線程的返回值,可由其他函數如pthread_join
來檢索獲取
等待線程退出並釋放資源pthread_join()
所需頭文件#include
<pthread.h>
函數原型int
pthread_join
((pthread_t
th,
void
**thread_return))
函數傳入值
th:等待線程的標識符
thread_return:用戶定義的指針,用來存儲被等待線程的返回值(不為NULL時)
函數返回值
成功:0
出錯:-1
代碼舉例
1.
#include<pthread.h>
2.
#include<stdio.h>
3.
#include<errno.h>
4.
5.
/*線程1*/
6.
void
thread1()
7.
{
8.
int
i=0;
9.
10.
while(1)
11.
{
12.
printf(thread1:%d/n,i);
13.
if(i>3)
14.
pthread_exit(0);
15.
i++;
16.
sleep(1);
17.
}
18.
}
19.
20.
/*線程2*/
21.
void
thread2()
22.
{
23.
int
i=0;
24.
25.
while(1)
26.
{
27.
printf(thread2:%d/n,i);
28.
if(i>5)
29.
pthread_exit(0);
30.
i++;
31.
sleep(1);
32.
}
33.
}
34.
35.
int
main()
36.
{
37.
pthread_t
t1,t2;
38.
39.
/*創建線程*/
40.
pthread_create(&t1,NULL,(void
*)thread1,NULL);
41.
pthread_create(&t2,NULL,(void
*)thread2,NULL);
42.
/*等待線程退出*/
43.
pthread_join(t1,NULL);
44.
pthread_join(t2,NULL);
45.
return
0;
46.
}
3同步與互斥
<1>互斥鎖
互斥鎖的操作主要包括以下幾個步驟。

互斥鎖初始化:pthread_mutex_init

互斥鎖上鎖:pthread_mutex_lock

互斥鎖判斷上鎖:pthread_mutex_trylock

互斥鎖接鎖:pthread_mutex_unlock

消除互斥鎖:pthread_mutex_destroy
1.
#include<pthread.h>
2.
#include<stdio.h>
3.
#include<errno.h>
4.
5.
int
i=0;/*共享變數*/
6.
pthread_mutex_t
mutex=PTHREAD_MUTEX_INITIALIZER;/*互斥鎖*/
7.
8.
void
thread1()
9.
{
10.
int
ret;
11.
while(1)
12.
{
13.
14.
15.
ret=pthread_mutex_trylock(&mutex);/*判斷上鎖*/
16.
17.
if(ret!=EBUSY)
18.
{
19.
pthread_mutex_lock(&mutex);/*上鎖*/
20.
printf(This
is
thread1:%d/n,i);
21.
i++;
22.
pthread_mutex_unlock(&mutex);/*解鎖*/
23.
}
24.
sleep(1);
25.
}
26.
}
27.
28.
void
thread2()
29.
{int
ret;
30.
while(1)
31.
{
32.
33.
ret=pthread_mutex_trylock(&mutex);
34.
if(ret!=EBUSY)
35.
{
36.
pthread_mutex_lock(&mutex);
37.
printf(This
is
thread2:%d/n,i);
38.
i++;
39.
pthread_mutex_unlock(&mutex);
40.
}
41.
sleep(1);
42.
}
43.
}
44.
int
main()
45.
{
46.
pthread_t
t1,t2;
47.
pthread_mutex_init(&mutex,NULL);
48.
pthread_create(&t1,NULL,(void
*)thread1,NULL);
49.
pthread_create(&t2,NULL,(void
*)thread2,NULL);
50.
51.
pthread_join(t1,NULL);
52.
pthread_join(t2,NULL);
53.
54.
pthread_mutex_destroy(&mutex);
55.
return
0;
56.
}
<2>信號量
未進行同步處理的兩個線程
1.
#include<pthread.h>
2.
#include<stdio.h>
3.
#include<errno.h>
4.
5.
int
i=0;
6.
void
thread1()
7.
{
8.
9.
while(1)
10.
{
11.
printf(This
is
thread1:%d/n,i);
12.
i++;
13.
sleep(1);
14.
}
15.
}
16.
17.
18.
void
thread2()
19.
{
20.
21.
while(1)
22.
{
23.
printf(This
is
thread2:%d/n,i);
24.
i++;
25.
sleep(1);
26.
}
27.
}
28.
29.
int
main()
30.
{
31.
pthread_t
t1,t2;
32.
33.
pthread_create(&t1,NULL,(void
*)thread1,NULL);
34.
pthread_create(&t2,NULL,(void
*)thread2,NULL);

閱讀全文

與linux線程共享內存相關的資料

熱點內容
網路加密伺服器有什麼作用 瀏覽:260
蘋果手機pdf怎麼保存 瀏覽:982
編譯器語法大嗎 瀏覽:27
隱私加密的分類 瀏覽:23
endnote文件直接放入文件夾 瀏覽:743
androidcamera幀率 瀏覽:65
飢荒官方伺服器怎麼初始化 瀏覽:579
蠟筆小新媽媽壓縮棉被子 瀏覽:603
pdf單頁保存 瀏覽:938
拼車小程序源碼gitlab 瀏覽:575
華為機器控制演算法專業碩士工薪 瀏覽:84
程序員游戲出包 瀏覽:29
天雲游app怎麼下載 瀏覽:262
utf8不可映射字元無法編譯 瀏覽:505
visualc編程pdf 瀏覽:650
加密獨角獸企業 瀏覽:809
天翼雲盤怎麼保存app 瀏覽:988
如何給磁碟進行加密 瀏覽:655
方舟手游如何收藏伺服器 瀏覽:520
如何自己組裝伺服器 瀏覽:96