pthread_create/join函數


轉自: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
    );

pthreadlinux系統的默認庫, 需手動鏈接-線程庫 -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()方法:Thread提供的讓一個線程去等待另一個線程完成。
當在某個程序執行流中(如main線程)調用其它線程(如t2線程)的join方法(t2.join()),調用線程(main線程)將被阻塞,直到被join()方法加入的join線程(t2.start())執行完成為止。
join源碼:
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線程,從而達到同步的目的。
多線程並行執行,每個線程先全部start再全部join;多個線程順序執行,每個依次start然后join。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM