二 Pthread 并發編程

Pthread 并發編程(二)——自底向上深入理解線程前言在本篇文章當中主要給大家介紹線程最基本的組成元素,以及在 pthread 當中給我們提供的一些線程的基本機制,因為很多語言的線程機制就是建立在 pthread 線程之上的,比如說 Python 和 Java,深入理解 pthread 的線程實現機制,可以極大的提升我們對于語言線程的認識 。希望能夠幫助大家深入理解線程 。
線程的基本元素首先我們需要了解一些我們在使用線程的時候的常用的基本操作 , 如果不是很了解沒有關系我們在后續的文章當中會仔細談論這些問題 。

  • 線程的常見的基本操作:
    • 線程的創建 。
    • 線程的終止 。
    • 線程之間的同步 。
    • 線程的調度 。
    • 線程當中的數據管理 。
    • 線程與進程之間的交互 。
  • 在 linux 當中所有的線程和進程共享一個地址空間 。
  • 【二 Pthread 并發編程】進程與線程之間共享一些內核數據結構:
    • 打開的文件描述符 。
    • 當前工作目錄 。
    • 用戶 id 和用戶組 id。
    • 全局數據段的數據 。
    • 進程的代碼 。
    • 信號(signals)和信號處理函數(signal handlers) 。
  • 線程獨有的:
    • 線程的 ID。
    • 寄存器線程和??臻g 。
    • 線程的棧當中的局部變量和返回地址 。
    • 信號掩碼 。
    • 線程自己的優先級 。
    • errno 。
在所有的 pthread 的接口當中,只有當函數的返回值是 0 的時候表示調用成功 。
線程等待在 pthread 的實現當中,每個線程都兩個特性:joinable 和 detached,當我們啟動一個線程的時候 (pthread_create) 線程的默認屬性是 joinable , 所謂 joinable 是表示線程是可以使用 pthread_join 進行同步的 。
當一個線程調用 pthread_join(T, ret),當這個函數返回的時候就表示線程 T 已經終止了,執行完成 。那么就可以釋放與線程 T 的相關的系統資源 。
如果一個線程的狀態是 detached 狀態的話 , 當線程結束的時候與這個線程相關的資源會被自動釋放掉,將資源歸還給系統,也就不需要其他的線程調用 pthread_join 來釋放線程的資源 。
pthread_join 函數簽名如下:
int pthread_join(pthread_t thread, void **retval);
  • thread 表示等待的線程 。
  • retval 如果 retval 不等于 NULL 則在 pthread_join 函數內部會將線程 thead 的退出狀態拷貝到 retval 指向的地址 。如果線程被取消了,那么 PTHREAD_CANCELED 將會被放在 retval 指向的地址 。
  • 函數的返回值
    • EDEADLK 表示檢測到死鎖了,比入兩個線程都調用 pthread_join 函數等待對方執行完成 。
    • EINVAL 線程不是一個 joinable 的線程,一種常見的情況就是 pthread_join 一個 detached 線程 。
    • EINVAL 當調用 pthrea_join 等待的線程正在被別的線程調用 pthread_join 等待 。
    • ESRCH 如果參數 thread 是一個無效的線程 , 比如沒有使用 pthread_create 進行創建 。
    • 0 表示函數調用成功 。
在下面的程序當中我們使用 pthread_join 函數去等待一個 detached 線程:
#include <stdio.h>#include <error.h>#include <errno.h>#include <pthread.h>#include <unistd.h>pthread_t t1, t2;void* thread_1(void* arg) {  int ret = pthread_detach(pthread_self());  sleep(2);  if(ret != 0)    perror("");  return NULL;}int main() {  pthread_create(&t1, NULL, thread_1, NULL);  sleep(1);  int ret = pthread_join(t1, NULL);  if(ret == ESRCH)    printf("No thread with the ID thread could be found.\n");  else if(ret == EINVAL) {    printf("thread is not a joinable thread or Another thread is already waiting to join with this thread\n");  }  return 0;}

推薦閱讀