當前位置:首頁 » 編程軟體 » linuxc多線程編程

linuxc多線程編程

發布時間: 2022-08-10 04:46:13

linux系統下,c語言pthread多線程編程傳參問題

3個線程使用的都是同一個info

代碼 Info_t *info= (Info_t *)malloc(sizeof(Info_t));只創建了一個info

pthread_create(&threads[i],NULL,calMatrix,(void *)info); 三個線程使用的是同一個

我把你的代碼改了下:

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>

intmtc[3]={0};//resultmatrix

typedefstruct
{
intprank;
int*mta;
int*mtb;
}Info_t;

void*calMatrix(void*arg)
{
inti;
Info_t*info=(Info_t*)arg;
intprank=info->prank;
fprintf(stdout,"calMatrix:prankis%d ",prank);

for(i=0;i<3;i++)
mtc[prank]+=info->mta[i]*info->mtb[i];

returnNULL;
}

intmain(intargc,char**argv)
{
inti,j,k=0;
intmta[3][3];
intmtb[3]={1};
Info_t*info=(Info_t*)malloc(sizeof(Info_t)*3);

for(i=0;i<3;i++)
for(j=0;j<3;j++)
mta[i][j]=k++;
/*3threads*/
pthread_t*threads=(pthread_t*)malloc(sizeof(pthread_t)*3);
fprintf(stdout," ");fflush(stdout);
for(i=0;i<3;i++)
{
info[i].prank=i;
info[i].mta=mta[i];
info[i].mtb=mtb;
pthread_create(&threads[i],NULL,calMatrix,(void*)(&info[i]));
}
for(i=0;i<3;i++)
pthread_join(threads[i],NULL);

fprintf(stdout," ====thematrixresult==== ");
fflush(stdout);

for(i=0;i<3;i++)
{
fprintf(stdout,"mtc[%d]=%d ",i,mtc[i]);
fflush(stdout);
}
return0;
}

矩陣的計算我忘記了,你運行看看結果對不對

② linux下多進程或者多線程編程的問題。新手,望指教!

你好,多進程或多線程,都不會阻塞當前語句代碼。為了您的理解,我就大膽舉下面兩個例子:
多進程:你可以看成是本來是一條路的,現在從中間拆成兩條,然後每一條路都有屬於自己這條路的代碼在運行。
多線程:你可以看成是一條路,然後分出車道,比如左車道和右車道甚至是停車道,然後每條車道都單獨通車,其他車道的不能對這條車道進行干擾。

所以,把一條路從中間拆成兩條,成本是很高的。但是把一條路分車道,成本就不是很高了。
對於您提出的main函數的疑問,當main函數最後執行完畢,程序退出後,所有的進程包括線程,都會被關閉的,哪怕你的程序中沒有關閉,操作系統也會幫你關閉的,現在的操作系統都非常的完善了。當然,也存在有線程或進程不被釋放的特殊情況,最好在編程中要記得釋放。

③ 如何看懂《Linux多線程服務端編程

:進程線程 每進程自獨立址空間同進程同進程系統功能劃重要決策點《Erlang程序設計》[ERL]進程比喻: 每自記憶(內存)與通談(消息傳遞)交流談既面談(同台伺服器)電談(同伺服器中國絡通信)面談電談區別於面談立即知道否死(crash,SIGCHLD)電談能通周期性跳判斷否著 些比喻設計布式系統採取角色扮演團隊幾各自扮演進程角色由進程代碼決定(管登錄、管消息發、管買賣等等)每自記憶知道別記憶要想知道別看能通交談(暫考慮共享內存種IPC)思考: ·容錯:萬突死 ·擴容:新途加進 ·負載均衡:甲挪給乙做 ·退休:甲要修復bug先別派新任務等做完手事情重啟 等等各種場景十便利 線程特點共享址空間高效共享數據台機器進程能高效共享代碼段(操作系統映射同物理內存)能共享數據進程量共享內存等於進程程序線程寫掩耳盜鈴 線程價值我認更發揮核處理器(multi-cores)效能單核代線程沒價值(想:要完任務CPU密集型線程沒優勢甚至線程切換銷線程反更慢;要完任務既CPU計算磁碟或中國絡IO則使用線程處某線程IO阻塞OS調度其線程執行雖效率確實要比任務順序執行效率要高種類型任務通單線程non-blocking IO+IO multiplexing模型(事件驅)提高效率採用線程式帶能僅僅編程簡單已)Alan Cox說:A 中國puter is a state machine.Threads are for people who can』t program state machines.(計算機台狀態機線程給些能編寫狀態機程序准備)塊CPU、執行單元確實Alan Cox所說按狀態機思路寫程序高效 二:單線程伺服器用編程模型 據我解高性能中國絡程序使用廣泛恐怕要數non-blocking IO + IO multiplexing種模型即Reactor模式 non-blocking IO + IO multiplexing種模型程序基本結構事件循環(event loop)事件驅(event-driven)事件調式實現業務邏輯: [cpp] view plain //代碼僅示意沒完整考慮各種情況 while(!done) { int timeout_ms = max(1000, getNextTimedCallback()); int retval = poll(fds, nfds, timeout_ms); if (retval0){ 處理IO事件調用戶IO event handler } } } select(2)/poll(2)伸縮性面足(描述符效率較低)Linux替換epoll(4)其操作系統應高性能替代品 Reactor模型優點明顯編程難效率錯僅用於讀寫socket連接建立(connect(2)/accept(2))甚至DNS解析都用非阻塞式進行提高並發度吞吐量(throughput)於IO密集應用錯選擇lighttpd內部fdevent結構十精妙值習 基於事件驅編程模型其本質缺點要求事件調函數必須非阻塞於涉及中國絡IO請求響應式協議容易割裂業務邏輯使其散布於調函數相容易理解維護 三:線程伺服器用編程模型 概幾種: a:每請求創建線程使用阻塞式IO操作Java 1.4引NIO前Java中國絡編程推薦做惜伸縮性佳(請求太操作系統創建許線程) b:使用線程池同使用阻塞式IO操作與第1種相比提高性能措施 c:使用non-blocking IO + IO multiplexing即Java NIO式 d:Leader/Follower等高級模式 默認情況我使用第3種即non-blocking IO + one loop per thread模式編寫線程C++中國絡服務程序 1:one loop per thread 種模型程序每IO線程event loop用於處理讀寫定事件(論周期性單)代碼框架跟單線程伺服器用編程模型節 libev作者說: One loop per thread is usually a good model. Doing this is almost never wrong, some times a better-performance model exists, but it is always a good start. 種式處: a:線程數目基本固定程序啟候設置頻繁創建與銷毀 b:便線程間調配負載 c:IO事件發線程固定同TCP連接必考慮事件並發 Event loop代表線程主循環需要讓哪線程干timer或IO channel(TCP連接)注冊哪線程loop即:實性要求connection單獨用線程;數據量connection獨占線程並數據處理任務攤另幾計算線程(用線程池);其要輔助性connections共享線程 比dbproxy線程用於專門處理客戶端發管理命令;線程用於處理客戶端發MySQL命令與端資料庫通信執行該命令該任務配給所事件線程處理 於non-trivial(定規模)服務端程序般採用non-blocking IO + IO multiplexing每connection/acceptor都注冊某event loop程序event loop每線程至event loop 線程程序event loop提更高要求線程安全要允許線程往別線程loop塞東西loop必須線程安全 dbproxy線程向其線程發任務通管道隊列實現比主線程accept連接表示該連接結構放入隊列並向管道寫入位元組計算線程自event loop注冊管道讀事件旦數據讀嘗試隊列取任務 2:線程池 於沒IO光計算任務線程使用event loop點浪費使用種補充案即用blocking queue實現任務隊列: [cpp] view plain typedef boost::functionFunctor; BlockingQueue taskQueue; //線程安全全局阻塞隊列 //計算線程 void workerThread() { while (running) //running變數全局標志 { Functor task = taskQueue.take(); //this blocks task(); //產品代碼需要考慮異處理 } } // 創建容量(並發數)N線程池 int N = num_of_中國puting_threads; for (int i = 0; i < N; ++i) { create_thread(&workerThread); //啟線程 } //向任務隊列追加任務 Foo foo; //Foocalc()員函數 boost::function task = boost::bind(&Foo::calc&foo); taskQueue.post(task); 除任務隊列用BlockingQueue實現數據產者消費者隊列即T數據類型非函數象queue消費者拿數據進行處理其實本質 3:總結 總結言我推薦C++線程服務端編程模式:one (event) loop per thread + thread pool: event loop用作IO multiplexing配合non-blockingIO定器; thread pool用做計算具體任務隊列或產者消費者隊列 種式寫伺服器程序需要優質基於Reactor模式中國絡庫支撐muo中國絡庫比dbproxy使用libevent 程序具體用幾loop、線程池等參數需要根據應用設定基本原則阻抗匹配(解釋見)使CPUIO都能高效運作所謂阻抗匹配原則: 池線程執行任務密集計算所佔間比重 P (0 < P <= 1)系統共 C CPU讓 C CPU 跑滿載線程池經驗公式 T = C/P(T hint考慮 P 值估計准確T 佳值浮 50%) 我再講經驗公式先驗證邊界條件確性 假設 C = 8P = 1.0線程池任務完全密集計算T = 8要 8 線程能讓 8 CPU 飽再沒用 CPU 資源已經耗光 假設 C = 8P = 0.5線程池任務半計算半等 IO T = 16考慮操作系統能靈合理調度 sleeping/writing/running 線程概 16 50%繁忙線程能讓 8 CPU 忙停啟更線程並能提高吞吐量反增加文切換銷降低性能 P < 0.2公式適用T 取固定值比 5*C 另外公式 C 定 CPU 總數配給項任務 CPU 數目比 8 核機器 4 核做項任務 C=4 四:進程間通信用TCP Linux進程間通信式:匿名管道(pipe)、具名管道(FIFO)、POSIX消息隊列、共享內存、信號(signals)及Socket同步原語互斥器(mutex)、條件變數(condition variable)、讀寫鎖(reader-writer lock)、文件鎖(record locking)、信號量(semaphore)等等 進程間通信我首選Sockets(主要指TCP我沒用UDP考慮Unix domain協議)其處於: 跨主機具伸縮性反都進程台機器處理能力夠自能用台機器處理進程散同局域中國台機器程序改改host:port配置能繼續用; TCP socketspipe都操作文件描述符用收發位元組流都read/write/fcntl/select/poll等同TCP雙向Linuxpipe單向進程間雙向通信兩文件描述符便;且進程要父關系才能用pipe些都限制pipe使用; TCP port由進程獨占且進程退操作系統自收文件描述符即使程序意外退給系統留垃圾程序重啟能比較容易恢復需要重啟操作系統(用跨進程mutex風險);且port獨占防止程序重復啟面進程搶port自沒初始化避免造意料外結; 與其IPC相比TCP協議處記錄、重現tcpmpWireshark解決兩進程間協議狀態爭端幫手性能(吞吐量、延遲)析利器我借編寫布式程序自化歸測試用tcp類工具進行壓力測試TCP能跨語言服務端客戶端必使用同種語言 布式系統軟體設計功能劃般應該進程單位宏觀看布式系統由運行台機器進程組進程間採用TCP連接通信 使用TCP連接處兩點:容易定位布式系統服務間依賴關系要機器運行netstat -tpna|grep 能立刻列用某服務客戶端址(Foreign Address列)客戶端機器用netstat或lsof命令找哪進程發起連接TCP短連接UDP則具備特性二通接收發送隊列度較容易定位中國絡或程序故障運行候netstat列印Recv-QSend-Q都應該接近0或者0附近擺Recv-Q保持變或持續增加則通意味著服務進程處理速度變慢能發死鎖或阻塞Send-Q保持變或持續增加能伺服器太忙、及處理能中國絡間某路由器或交換機故障造丟包甚至伺服器掉線些素都能表現數據發送通持續監控Recv-QSend-Q能及早預警性能或用性故障服務端線程阻塞造Recv-Q客戶端Send-Q激增例: [cpp] view plain $netstat -tn Proto Recv-Q Send-Q Local Address Foreign tcp 78393 0 10.0.0.10:2000 10.0.0.10:39748 #服務端連接 tcp 0 132608 10.0.0.10:39748 10.0.0.10:2000 #客戶端連接 tcp 0 52 10.0.0.10:22 10.0.0.4:55572 五:線程伺服器適用場合 要台核機器提供種服務或執行任務用模式: a:運行單線程進程; b:運行線程進程; c:運行單線程進程; d:運行線程進程; 考慮場景:使用速率50MB/s數據壓縮庫進程創建銷毀銷800微秒線程創建銷毀銷50微秒何執行壓縮任務 要偶爾壓縮1GB文本文件預計運行間20s起進程做合理進程啟銷毀銷遠遠於實際任務耗 要經壓縮500kB文本數據預計運行間10ms每都起進程 似乎點浪費每單獨起線程做 要頻繁壓縮10kB文本數據預計運行間200微秒每起線程似 乎浪費直接前線程搞定用線程池每壓縮任務交給線程池避免阻塞前線程(特別要避免阻塞IO線程) 由見線程並萬靈丹(silver bullet) 1:必須使用單線程場合 據我所知兩種場合必須使用單線程: a:程序能fork(2); 實際編程應該保證單線程程序能進行fork(2)線程程序能調用fork(2)做遇麻煩: fork般能線程程序調用Linuxfork克隆前線程thread of control隆其線程fork除前線程外其線程都消失 造種危險局面其線程能處於臨界區內持某鎖突死亡再沒機解鎖進程試圖再同mutex加鎖立即死鎖fork進程相於處於signal handler(知道調用fork父進程線程調用函數信號發場景)能調用線程安全函數(除非重入)能調用非同步信號安全函數比fork進程能調用: mallocmalloc訪問全局狀態幾乎肯定加鎖; 任何能配或釋放內存函數比snprintf; 任何Pthreads函數; printf系列函數其線程能恰持stdout/stderr鎖; 除man 7 signal明確列信號安全函數外任何函數 線程調用fork唯安全做fork立即調用exec執行另程序徹底隔斷進程與父進程聯系 線程環境調用fork產進程進程內部存線程父進程調用fork線程副本 使用fork創建進程進程通繼承整址空間副本父進程繼承所互斥量、讀寫鎖條件變數狀態父進程某線程占鎖則進程同占些鎖問題進程並包含占鎖線程副本所進程沒辦知道占哪些鎖並且需要釋放哪些鎖 盡管Pthread提供pthread_atfork函數試圖繞問題使代碼變混亂《Programming With Posix Threads》書作者說:Avoid using fork in threaded code except where the child process will immediately exec a new program. b:限製程序CPU佔用率; 容易理解比8核伺服器單線程程序即便發busy-wait占滿1core其CPU使用率12.5%種壞情況系統87.5%計算資源供其服務進程使用 於些輔助性程序必須主要服務進程運行同台機器做單線程能避免搶奪系統計算資

④ linux下C語言編程線程有什麼好處呢

進程和線程都是由操作系統所體會的程序運行的基本單元,系統利用該基本單元實現系統對應用的並發性。進程和線程的區別在於:

線程的劃分尺度小於進程,使得多線程程序的並發性搞。

另外,進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大地提高了程序的運行效率。

線程在執行過程中與進程還是有區別的。每個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。但是線程不能夠獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。

從邏輯角度來看,多線程的意義在於一個應用程序中,有多個執行部分可以同時執行。但操作系統並沒有將多個線程看做多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別。

進程(Process)是最初定義在Unix等多用戶、多任務操作系統環境下用於表示應用程序在內存環境中基本執行單元的概念。以Unix操作系統為例,進程是Unix操作系統環境中的基本成分、是系統資源分配的基本單位。Unix操作系統中完成的幾乎所有用戶管理和資源分配等工作都是通過操作系統對應用程序進程的控制來實現的。

一般你運行一個應用程序,就生成了一個進程, 這個進程擁有自己的內存空間,

這個進程還可以內部生成多個線程, 這些線程之間共用一個進程的內存空存空間,所以線程之間共享內存是很容易做到的,多線程協作比多進程協作快一些,而且安全.

在windows跟unix上面,進程,線程的實現方法都是不一樣的.

⑤ 淺談linux 多線程編程和 windows 多線程編程的異同

首先我們講講為什麼要採用多線程編程,其實並不是所有的程序都必須採用多線程,有些時候採用多線程,性能還沒有單線程好。所以我們要搞清楚,什麼時候採用多線程。採用多線程的好處如下:
(1)因為多線程彼此之間採用相同的地址空間,共享大部分的數據,這樣和多進程相比,代價比較節儉,因為多進程的話,啟動新的進程必須分配給它獨立的地址空間,這樣需要數據表來維護代碼段,數據段和堆棧段等等。
(2)多線程和多進程相比,一個明顯的優點就是線程之間的通信了,對不同進程來說,它們具有獨立的數據空間,要進行數據的傳遞只能通過通信的方式進行,這種方式不僅費時,而且很不方便。但是對於多線程就不一樣了。他們之間可以直接共享數據,比如最簡單的方式就是共享全局變數。但是共享全部變數也要注意哦,呵呵,必須注意同步,不然後果你知道的。呵呵。
(3)在多cpu的情況下,不同的線程可以運行不同的cpu下,這樣就完全並行了。
反正我覺得在這種情況下,採用多線程比較理想。比如說你要做一個任務分2個步驟,你為提高工作效率,你可以多線程技術,開辟2個線程,第一個線程就做第一步的工作,第2個線程就做第2步的工作。但是你這個時候要注意同步了。因為只有第一步做完才能做第2步的工作。這時,我們可以採用同步技術進行線程之間的通信。
針對這種情況,我們首先講講多線程之間的通信,在windows平台下,多線程之間通信採用的方法主要有:
(1)共享全局變數,這種方法是最容易想到的,呵呵,那就首先講講吧,比如說吧,上面的問題,第一步要向第2步傳遞收據,我們可以之間共享全局變數,讓兩個線程之間傳遞數據,這時主要考慮的就是同步了,因為你後面的線程在對數據進行操作的時候,你第一個線程又改變了數據的內容,你不同步保護,後果很嚴重的。你也知道,這種情況就是讀臟數據了。在這種情況下,我們最容易想到的同步方法就是設置一個bool flag了,比如說在第2個線程還沒有用完數據前,第一個線程不能寫入。有時在2個線程所需的時間不相同的時候,怎樣達到最大效率的同步,就比較麻煩了。咱們可以多開幾個緩沖區進行操作。就像生產者消費者一樣了。如果是2個線程一直在跑的,由於時間不一致,緩沖區遲早會溢出的。在這種情況下就要考慮了,是不讓數據寫入還是讓數據覆蓋掉老的數據,這時候就要具體問題具體分析了。就此打住,呵呵。就是用bool變數控制同步,linux 和windows是一樣的。
既然講道了這里,就再講講其它同步的方法。同樣 針對上面的這個問題,共享全局變數同步問題。除了採用bool變數外,最容易想到的方法就是互斥量了。呵呵,也就是傳說中的加鎖了。windows下加鎖和linux下加鎖是類似的。採用互斥量進行同步,要想進入那段代碼,就先必須獲得互斥量。
linux上互斥量的函數是:
windows下互斥量的函數有:createmutex 創建一個互斥量,然後就是獲得互斥量waitforsingleobject函數,用完了就釋放互斥量ReleaseMutex(hMutex),當減到0的時候 內核會才會釋放其對象。下面是windows下與互斥的幾個函數原型。
HANDLE WINAPI CreateMutex(
__in LPSECURITY_ATTRIBUTES lpMutexAttributes,
__in BOOL bInitialOwner,
__in LPCTSTR lpName
);
可以可用來創建一個有名或無名的互斥量對象
第一參數 可以指向一個結構體SECURITY_ATTRIBUTES一般可以設為null;
第二參數 指當時的函數是不是感應感應狀態 FALSE為當前擁有者不會創建互斥
第三參數 指明是否是有名的互斥對象 如果是無名 用null就好。
DWORD WINAPI WaitForSingleObject(
__in HANDLE hHandle,
__in DWORD dwMilliseconds
);
第一個是 創建的互斥對象的句柄。第二個是 表示將在多少時間之後返回 如果設為宏INFINITE 則不會返回 直到用戶自己定義返回。
對於linux操作系統,互斥也是類似的,只是函數不同罷了。在linux下,和互斥相關的幾個函數也要閃亮登場了。
pthread_mutex_init函數:初始化一個互斥鎖;
pthread_mutex_destroy函數:注銷一個互斥鎖;
pthread_mutex_lock函數:加鎖,如果不成功,阻塞等待;
pthread_mutex_unlock函數:解鎖;
pthread_mutex_trylock函數:測試加鎖,如果不成功就立即返回,錯誤碼為EBUSY;
至於這些函數的用法,google上一搜,就出來了,呵呵,在這里不多講了。windows下還有一個可以用來保護數據的方法,也是線程同步的方式
就是臨界區了。臨界區和互斥類似。它們之間的區別是,臨界區速度快,但是它只能用來同步同一個進程內的多個線程。臨界區的獲取和釋放函數如下:
EnterCriticalSection() 進入臨界區; LeaveCriticalSection()離開臨界區。 對於多線程共享內存的東東就講到這里了。
(2)採用消息機制進行多線程通信和同步,windows下面的的消息機制的函數用的多的就是postmessage了。Linux下的消息機制,我用的較少,就不在這里說了,如果誰熟悉的,也告訴我,呵呵。
(3)windows下的另外一種線程通信方法就是事件和信號量了。同樣針對我開始舉得例子,2個線程同步,他們之間傳遞信息,可以採用事件(Event)或信號量(Semaphore),比如第一個線程完成生產的數據後,就必須告訴第2個線程,他已經把數據准備好了,你可以來取走了。第2個線程就把數據取走。呵呵,這里可以採用消息機制,當第一個線程准備好數據後,就直接postmessage給第2個線程,按理說採用postmessage一個線程就可以搞定這個問題了。呵呵,不是重點,省略不講了。
對於linux,也有類似的方法,就是條件變數了,呵呵,這里windows和linux就有不同了。要特別講講才行。
對於windows,採用事件和信號量同步時候,都會使用waitforsingleobject進行等待的,這個函數的第一個參數是一個句柄,在這里可以是Event句柄,或Semaphore句柄,第2個參數就是等待的延遲,最終等多久,單位是ms,如果這個參數為INFINITE,那麼就是無限等待了。釋放信號量的函數為ReleaseSemaphore();釋放事件的函數為SetEvent。當然使用這些東西都要初始化的。這里就不講了。Msdn一搜,神馬都出來了,呵呵。神馬都是浮雲!
對於linux操作系統,是採用條件變數來實現類似的功能的。Linux的條件變數一般都是和互斥鎖一起使用的,主要的函數有:
pthread_mutex_lock ,
pthread_mutex_unlock,
pthread_cond_init
pthread_cond_signal
pthread_cond_wait
pthread_cond_timewait
為了和windows操作系統進行對比,我用以下表格進行比較:

對照以上表格,總結如下:
(1) Pthread_cleanup_push,Pthread_cleanup_pop:
這一對函數push和pop的作用是當出現異常退出時,做一些清除操作,即當在push和pop函數之間異常退出,包括調用pthread_exit退出,都會執行push裡面的清除函數,如果有多個push,注意是是棧,先執行後面的那個函數,在執行前面的函數,但是注意當在這2個函數之間通過return 退出的話,執不執行push後的函數就看pop函數中的參數是不是為0了。還有當沒有異常退出時,等同於在這裡面return退出的情況,即:當pop函數參數不為0時,執行清除操作,當pop函數參數為0時,不執行push函數中的清除函數。
(2)linux的pthread_cond_signal和SetEvent的不同點
Pthread_cond_singal釋放信號後,當沒有Pthread_cond_wait,信號馬上復位了,這點和SetEvent不同,SetEvent是不會復位的。詳解如下:
條件變數的置位和復位有2種常用模型:第一種模型是當條件變數置位時(signaled)以後,如果當前沒有線程在等待,其狀態會保持為置位(signaled),直到有等待的線程進入被觸發,其狀態才會變為unsignaled,這種模型以採用Windows平台上的Auto-set Event 為代表。
第2種模型則是Linux平台的pthread所採用的模型,當條件變數置位(signaled)以後,即使當前沒有任何線程在等待,其狀態也會恢復為復位(unsignaled)狀態。
條件變數在Linux平台上的這種模型很難說好壞,在實際應用中,我們可以對
代碼稍加改進就可以避免這種差異的發生。由於這種差異只會發生在觸發沒有被線程等待在條件變數的時刻,因此我們只需要掌握好觸發的時機即可。最簡單的做法是增加一個計數器記錄等待線程的個數,在決定觸發條件變數前檢查該變數即可。
示例 使用 pthread_cond_wait() 和 pthread_cond_signal()
pthread_mutex_t count_lock;
pthread_cond_t count_nonzero;
unsigned count;
decrement_count()
{
pthread_mutex_lock(&count_lock);
while (count == 0)
pthread_cond_wait(&count_nonzero, &count_lock);
count = count - 1;
pthread_mutex_unlock(&count_lock);
}
increment_count()
{
pthread_mutex_lock(&count_lock);
if (count == 0)
pthread_cond_signal(&count_nonzero);
count = count + 1;
pthread_mutex_unlock(&count_lock);
}
(3) 注意Pthread_cond_wait條件返回時互斥鎖的解鎖問題
extern int pthread_cond_wait __P ((pthread_cond_t *__cond,pthread_mutex_t *__mutex));
調用這個函數時,線程解開mutex指向的鎖並被條件變數cond阻塞。線程可以被函數pthread_cond_signal和函數 pthread_cond_broadcast喚醒線程被喚醒後,它將重新檢查判斷條件是否滿足,如果還不滿足,一般說來線程應該仍阻塞在這里,被等待被下一次喚醒。如果在多線程中採用pthread_cond_wait來等待時,會首先釋放互斥鎖,當等待的信號到來時,再次獲得互斥鎖,因此在之後要注意手動解鎖。舉例如下:
#include
#include
#include
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; /*初始化互斥鎖*/
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; //初始化條件變數
void *thread1(void *);
void *thread2(void *);
int i=1;
int main(void)
{
pthread_t t_a;
pthread_t t_b;
pthread_create(&t_a,NULL,thread1,(void *)NULL);/*創建進程t_a*/
pthread_create(&t_b,NULL,thread2,(void *)NULL); /*創建進程t_b*/
pthread_join(t_b, NULL);/*等待進程t_b結束*/
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
exit(0);
}
void *thread1(void *junk)
{
for(i=1;i<=9;i++)
{
printf("IN one\n");
pthread_mutex_lock(&mutex);//
if(i%3==0)
pthread_cond_signal(&cond);/*,發送信號,通知t_b進程*/
else
printf("thead1:%d\n",i);
pthread_mutex_unlock(&mutex);//*解鎖互斥量*/
printf("Up Mutex\n");
sleep(3);
}
}
void *thread2(void *junk)
{
while(i<9)
{
printf("IN two \n");
pthread_mutex_lock(&mutex);
if(i%3!=0)
pthread_cond_wait(&cond,&mutex);/*等待*/
printf("thread2:%d\n",i);
pthread_mutex_unlock(&mutex);
printf("Down Mutex\n");
sleep(3);
}
}
輸出如下:
IN one
thead1:1
Up Mutex
IN two
IN one
thead1:2
Up Mutex
IN one
thread2:3
Down Mutex
Up Mutex
IN one
thead1:4
Up Mutex
IN two
IN one
thead1:5
Up Mutex
IN one
Up Mutex
thread2:6
Down Mutex
IN two
thread2:6
Down Mutex
IN one
thead1:7
Up Mutex
IN one
thead1:8
Up Mutex
IN two
IN one
Up Mutex
thread2:9
Down Mutex
注意藍色的地方,有2個thread2:6,其實當這個程序多執行幾次,i=3和i=6時有可能多列印幾個,這里就是競爭鎖造成的了。
(4)另外要注意的Pthread_cond_timedwait等待的是絕對時間,這個和WaitForSingleObject是不同的,Pthread_cond_timedwait在網上也有討論。如下:這個問題比較經典,我把它搬過來。
thread_a :
pthread_mutex_lock(&mutex);
//do something
pthread_mutex_unlock(&mutex)
thread_b:
pthread_mutex_lock(&mutex);
//do something
pthread_cond_timedwait(&cond, &mutex, &tm);
pthread_mutex_unlock(&mutex)
有如上兩個線程thread_a, thread_b,現在如果a已經進入了臨界區,而b同時超時了,那麼b會從pthread_cond_timedwait返回嗎?如果能返回,那豈不是a,b都在臨界區?如果不能返回,那pthread_cond_timedwait的定時豈不是就不準了?
大家討論有價值的2點如下:
(1) pthread_cond_timedwait (pthread_cond_t *cv, pthread_mutex_t *external_mutex, const struct timespec *abstime) -- This function is a time-based variant of pthread_cond_wait. It waits up to abstime amount of time for cv to be notified. If abstime elapses before cv is notified, the function returns back to the caller with an ETIME result, signifying that a timeout has occurred. Even in the case of timeouts, the external_mutex will be locked when pthread_cond_timedwait returns.
(2) 2.1 pthread_cond_timedwait行為和pthread_cond_wait一樣,在返回的時候都要再次lock mutex.
2 .2pthread_cond_timedwait所謂的如果沒有等到條件變數,超時就返回,並不確切。
如果pthread_cond_timedwait超時到了,但是這個時候不能lock臨界區,pthread_cond_timedwait並不會立即返回,但是在pthread_cond_timedwait返回的時候,它仍在臨界區中,且此時返回值為ETIMEDOUT。
關於pthread_cond_timedwait超時返回的問題,我也認同觀點2。
附錄:
int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict_attr,void*(*start_rtn)(void*),void *restrict arg);
返回值:若成功則返回0,否則返回出錯編號
返回成功時,由tidp指向的內存單元被設置為新創建線程的線程ID。attr參數用於制定各種不同的線程屬性。新創建的線程從start_rtn函數的地址開始運行,該函數只有一個無指針參數arg,如果需要向start_rtn函數傳遞的參數不止一個,那麼需要把這些參數放到一個結構中,然後把這個結構的地址作為arg的參數傳入。
linux下用C開發多線程程序,Linux系統下的多線程遵循POSIX線程介面,稱為pthread。
由 restrict 修飾的指針是最初唯一對指針所指向的對象進行存取的方法,僅當第二個指針基於第一個時,才能對對象進行存取。對對象的存取都限定於基於由 restrict 修飾的指針表達式中。 由 restrict 修飾的指針主要用於函數形參,或指向由 malloc() 分配的內存空間。restrict 數據類型不改變程序的語義。 編譯器能通過作出 restrict 修飾的指針是存取對象的唯一方法的假設,更好地優化某些類型的常式。
第一個參數為指向線程標識符的指針。
第二個參數用來設置線程屬性。
第三個參數是線程運行函數的起始地址。
第四個參數是運行函數的參數。
因為pthread不是linux系統的庫,所以在編譯時注意加上-lpthread參數,以調用靜態鏈接庫。
終止線程:
如果在進程中任何一個線程中調用exit或_exit,那麼整個進行會終止,線程正常的退出方式有:
(1) 線程從啟動常式中返回(return)
(2) 線程可以被另一個進程終止(kill);
(3) 線程自己調用pthread_exit函數
#include
pthread_exit
線程等待:
int pthread_join(pthread_t tid,void **rval_ptr)
函數pthread_join用來等待一個線程的結束。函數原型為:
extern int pthread_join __P (pthread_t __th, void **__thread_return);
第一個參數為被等待的線程標識符,第二個參數為一個用戶定義的指針,它可以用來存儲被等待線程的返回值。這個函數是一個線程阻塞的函數,調用它的函數將一直等待到被等待的線程結束為止,當函數返回時,被等待線程的資源被收回。
對於windows線程的創建東西,就不列舉了,msdn上 一搜就出來了。呵呵。今天就講到這里吧,希望是拋磚引玉,大家一起探討,呵呵。部分內容我也是參考internet的,特此對原作者表示感謝!

⑥ 在Linux下用C++創建新線程

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
void* thread(void* arg)
{
printf ("The child process...\n");
}

int main(int argc, char *argv[])
{
pthread_t id;
int i,ret;
ret=pthread_create(&id,NULL,(void *)thread,NULL);
if(ret!=0)
{
printf ("Create pthread error!\n");
exit (1);
}

}
程序如上就可以編譯。
它屬於linux下C編程中多線程編程的范圍。
用命令
gcc -lpthread 1.c -o 1
./1
就可以出結果。
多線程編程的基礎可以參考
http://hi..com/huifeng00/blog/item/ed13ddc0d6c59c170ff47715.html

⑦ Linux C 怎麼實現兩個線程同步讀取兩個內存的數據

在Linux系統中使用C/C++進行多線程編程時,我們遇到最多的就是對同一變數的多線程讀寫問題,大多情況下遇到這類問題都是通過鎖機制來處理,但這對程序的性能帶來了很大的影響,當然對於那些系統原生支持原子操作的數據類型來說,我們可以使用原子操作來處理,這能對程序的性能會得到一定的提高。那麼對於那些系統不支持原子操作的自定義數據類型,在不使用鎖的情況下如何做到線程安全呢?本文將從線程局部存儲方面,簡單講解處理這一類線程安全問題的方法。

一、數據類型
在C/C++程序中常存在全局變數、函數內定義的靜態變數以及局部變數,對於局部變數來說,其不存在線程安全問題,因此不在本文討論的范圍之內。全局變數和函數內定義的靜態變數,是同一進程中各個線程都可以訪問的共享變數,因此它們存在多線程讀寫問題。在一個線程中修改了變數中的內容,其他線程都能感知並且能讀取已更改過的內容,這對數據交換來說是非常快捷的,但是由於多線程的存在,對於同一個變數可能存在兩個或兩個以上的線程同時修改變數所在的內存內容,同時又存在多個線程在變數在修改的時去讀取該內存值,如果沒有使用相應的同步機制來保護該內存的話,那麼所讀取到的數據將是不可預知的,甚至可能導致程序崩潰。
如果需要在一個線程內部的各個函數調用都能訪問、但其它線程不能訪問的變數,這就需要新的機制來實現,我們稱之為Static memory local to a thread (線程局部靜態變數),同時也可稱之為線程特有數據(TSD: Thread-Specific Data)或者線程局部存儲(TLS: Thread-Local Storage)。這一類型的數據,在程序中每個線程都會分別維護一份變數的副本(),並且長期存在於該線程中,對此類變數的操作不影響其他線程。如下圖:

二、一次性初始化
在講解線程特有數據之前,先讓我們來了解一下一次性初始化。多線程程序有時有這樣的需求:不管創建多少個線程,有些數據的初始化只能發生一次。列如:在C++程序中某個類在整個進程的生命周期內只能存在一個實例對象,在多線程的情況下,為了能讓該對象能夠安全的初始化,一次性初始化機制就顯得尤為重要了。——在設計模式中這種實現常常被稱之為單例模式(Singleton)。Linux中提供了如下函數來實現一次性初始化:
#include <pthread.h>

// Returns 0 on success, or a positive error number on error
int pthread_once (pthread_once_t *once_control, void (*init) (void));
利用參數once_control的狀態,函數pthread_once()可以確保無論有多少個線程調用多少次該函數,也只會執行一次由init所指向的由調用者定義的函數。init所指向的函數沒有任何參數,形式如下:
void init (void)
{
// some variables initializtion in here
}
另外,參數once_control必須是pthread_once_t類型變數的指針,指向初始化為PTHRAD_ONCE_INIT的靜態變數。在C++0x以後提供了類似功能的函數std::call_once (),用法與該函數類似。使用實例請參考https://github.com/ApusApp/Swift/blob/master/swift/base/singleton.hpp實現。

⑧ c語言多線程編程問題

C語言中多線程的實現原理就是線程的原理,本人只了解Linux下面的C,linux下面的線程,不就是進程中的一個控制流么,相對來說代碼很簡單,但是原理卻是很復雜,很難說清,還需要自己詳細學習研究,下面是一個很簡單的例子,哪邊都能找到,自己運行下看看吧
#include <pthread.h>
#include <stdio.h>
#include <sys/time.h>
#include <string.h>
#define MAX 10
pthread_t thread[2];
pthread_mutex_t mut;
int number=0, i;
void *thread1()
{
printf ("thread1 : I'm thread 1\n");
for (i = 0; i < MAX; i++)
{
printf("thread1 : number = %d\n",number);
pthread_mutex_lock(&mut);
number++;
pthread_mutex_unlock(&mut);
sleep(2);
}
printf("thread1 :主函數在等我完成任務嗎?\n");
pthread_exit(NULL);
}
void *thread2()
{
printf("thread2 : I'm thread 2\n");
for (i = 0; i < MAX; i++)
{
printf("thread2 : number = %d\n",number);
pthread_mutex_lock(&mut);
number++;
pthread_mutex_unlock(&mut);
sleep(3);
}
printf("thread2 :主函數在等我完成任務嗎?\n");
pthread_exit(NULL);
}
void thread_create(void)
{
int temp;
memset(&thread, 0, sizeof(thread)); //comment1
/*創建線程*/
if((temp = pthread_create(&thread[0], NULL, thread1, NULL)) != 0) //comment2
printf("線程1創建失敗!\n");
else
printf("線程1被創建\n");
if((temp = pthread_create(&thread[1], NULL, thread2, NULL)) != 0) //comment3
printf("線程2創建失敗");
else
printf("線程2被創建\n");
}
void thread_wait(void)
{
/*等待線程結束*/
if(thread[0] !=0) { //comment4
pthread_join(thread[0],NULL);
printf("線程1已經結束\n");
}
if(thread[1] !=0) { //comment5
pthread_join(thread[1],NULL);
printf("線程2已經結束\n");
}
}
int main()
{
/*用默認屬性初始化互斥鎖*/
pthread_mutex_init(&mut,NULL);
printf("我是主函數哦,我正在創建線程,呵呵\n");
thread_create();
printf("我是主函數哦,我正在等待線程完成任務阿,呵呵\n");
thread_wait();
return 0;
}

⑨ linux下C多線程編程,為每個文件創建一個線程,轉換內容大小寫

你main里創建完線程就直接退出了,線程還沒來的及幹活就結束當然不行了。需要加pthread_join等待,像下面這樣:
int main(int argc, char ** argv)
{
pthread_t tid[10];
int i;
for(i=1; i<argc; i++)
{
if(pthread_create(&tid[i], NULL, thr_convert, (void*)argv[i]) != 0)
{
perror("pthread_create");
exit(1);
}
}
for(i=1; i<argc; i++)
pthread_join(tid[i],NULL);

return EXIT_SUCCESS;
}

⑩ linux下C編程多線程同步和非同步的區別,如何能實現程序的同步

同步和非同步的區別:
1、同步就是說多個任務之間是有先後關系的,一個任務需要等待另一個任務執行完畢才能繼續執行。
2、非同步就是說多個任務之間沒有先後關系,不需要相互等待各做各的事。
同步編程方法:
1、信號量
2、互斥量
非同步無需考慮資源沖突,不需特別處理。

熱點內容
androidactivity生命 發布:2024-04-27 07:33:48 瀏覽:84
win2008伺服器搭建網站 發布:2024-04-27 07:26:51 瀏覽:640
java的vector 發布:2024-04-27 07:05:00 瀏覽:204
舊電腦共享伺服器 發布:2024-04-27 06:32:21 瀏覽:339
java程序練習 發布:2024-04-27 06:24:00 瀏覽:438
sql30 發布:2024-04-27 06:22:10 瀏覽:55
怎樣防止sql注入 發布:2024-04-27 06:11:25 瀏覽:236
安卓為什麼不能登蘋果系統的游戲 發布:2024-04-27 06:11:23 瀏覽:601
編程日課 發布:2024-04-27 05:56:54 瀏覽:620
漏洞上傳工具 發布:2024-04-27 05:50:58 瀏覽:717