轉自:https://blog.csdn.net/wushuomin/article/details/80051295
1.pthread_create
#include <pthread.h> int pthread_create( pthread_t *restrict tidp, //新創建的線程ID指向的內存單元。 const pthread_attr_t *restrict attr, //線程屬性,默認為NULL void *(*start_rtn)(void *), //新創建的線程從start_rtn函數的地址開始運行 void *restrict arg //默認為NULL。若上述函數需要參數,將參數放入結構中並將地址作為arg傳入。 );
它的功能是創建線程(實際上就是確定調用該線程函數的入口點),在線程創建以后,就開始運行相關的線程函數。
pthread_create
的返回值 表示成功,返回0;表示出錯,返回表示-1。
內存泄漏問題:
在默認情況下通過pthread_create
函數創建的線程是非分離屬性的,由pthread_create函數的第二個參數決定,在非分離的情況下,當一個線程結束的時候,它所占用的系統資源並沒有完全真正的釋放,也沒有真正終止。
對於結合的線程:
只有在pthread_join
函數返回時,該線程才會釋放自己的資源。或者是設置在分離屬性的情況下,一個線程結束會立即釋放它所占用的資源。
設置屬性分離:
void run() { return; } int main(){ pthread_t thread; pthread_attr_t attr; pthread_attr_init( &attr ); pthread_attr_setdetachstate(&attr,1); pthread_create(&thread, &attr, run, 0); //第二個參數決定了分離屬性 //...... return 0; }
2.pthread_join
int pthread_join( pthread_t tid, //需要等待的線程,指定的線程必須位於當前的進程中,而且不得是分離線程 void **status //線程tid所執行的函數返回值(返回值地址需要保證有效),其中status可以為NULL );
pthread
非linux
系統的默認庫, 需手動鏈接-線程庫 -lpthread
返回值:
- 調用成功返回0.
- ESRCH描述: 沒有找到與給定的線程ID 相對應的線程。(如果多個線程等待同一個線程終止,則所有等待線程將一直等到目標線程終止。然后一個等待線程成功返回。其余的等待線程將失敗返回ESRCH錯誤)
- EDEADLK 描述: 將出現死鎖,如一個線程等待其本身,或者線程A和線程B 互相等待。
- EINVAL描述: 與給定的線程ID相對應的線程是分離線程。
pthread_join()
函數會一直阻塞調用線程,直到指定的線程終止。當pthread_join()
返回之后,應用程序可回收與已終止線程關聯的任何數據存儲空間。
但是,同時需要注意,一定要和上面創建的某一線程配套使用,這樣還可以起到互斥的作用。否則多線程可能搶占CPU資源,導致運行結果不確定。
//鏈接中舉了個例子,非常好。
配套使用,使得線程執行順序固定:(但這樣就使得多線程變為了單線程執行。沒什么意義了,類似函數調用?)
//這樣才是按順序的。 pthread_create(&t, 0, print1, NULL); pthread_join(t, NULL); pthread_create(&t1, 0, print2, NULL); pthread_join(t1, NULL); pthread_create(&t2, 0, print3, NULL); pthread_join(t2, NULL);
3.join的作用
https://www.jianshu.com/p/1007f0c13f7f,講的非常好,代碼例子,https://zhuanlan.zhihu.com/p/99374488
join源碼:join()方法:Thread提供的讓一個線程去等待另一個線程完成。當在某個程序執行流中(如main線程)調用其它線程(如t2線程)的join方法(t2.join()),調用線程(main線程)將被阻塞,直到被join()方法加入的join線程(t2.start())執行完成為止。
public final synchronized void join(long millis) throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (millis == 0) { while (isAlive()) { wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay);//調用wait阻塞調用方 now = System.currentTimeMillis() - base; } } }
join方法的原理就是調用相應線程的wait方法進行等待操作的。例如:
- A線程中調用了B線程的join方法,則相當於在A線程中調用了B線程的wait方法,
- 當B線程執行完(或者到達等待時間),B線程會自動調用自身的notifyAll方法喚醒A線程,從而達到同步的目的。