POSIX 線程編程(一)簡介

簡介


在共享內存的多處理器結構中,能夠用線程來實現並行。對於UNIX系統, IEEE POSIX 1003.1c標準規定了C語言線程編程接口的標準。這份標準的實現就是POSIX threads, 或者稱爲Pthreads.node

本文開始先介紹線程的基本概念,動機和設計方面的一些考慮。 接下來是Pthreads API 的三個主要部分:線程管理,互斥鎖和 條件變量。本文自始至終會貫穿大量的示例代碼來展現如何使用Pthread API的每一部分。程序員

Pthreads 概述

線程是什麼?

  • 從技術角度講,一個線程是一個獨立的指令流能夠被操做系統調用運行。But what does this mean?

     

  • 從程序員的角度講,獨立於主程序而單獨運行的「程序」能夠被稱爲一個線程。

     

  • 更進一步的講, 想象一個包含不少子程序的主程序 (a.out) . 而後想象全部這些子程序都能操做系統調用同時而且獨立的運行。這就是一個多線程的程序。

     

  • 這是怎麼完成的呢?
  • 在理解線程以前, 先要理解UNIX系統下的進程。 一個進程是由操做系統建立的, 而且要求大量的"開銷"。進程包含關於程序資源的信息和程序的執行狀態,包括:
    • 進程ID,進程組ID, 用戶ID,和組ID
    • 環境
    • 工做目錄
    • 程序指令
    • 寄存器
    • 文件描述符
    • 信號操做
    • 共享庫
    • 進程通訊工具 (例如消息隊列,管道,信號量,或者共享內存 ).

                                    UNIX進程                                                                                              線程web

 

  • 線程使用並存在在這些進程資源中,線程能夠被操做系統調用並獨立運行, 很大程度上是由於它只複製了不多量的做爲可執行代碼存在的必須重要資源。編程

  • 一個線程完成獨立的控制流是由於它維護本身擁有的:安全

    • 棧指針
    • 寄存器
    • 調度優先級
    • 待定和阻塞信號集合
    • 線程特有的數據
  • 所以,簡而言之,在UNIX系統環境中一個線程:多線程

    • 存在在一個進程中並使用進程資源
    • 只要父進程存在而且操做系統支持就一直擁有本身獨立的控制流
    • 僅複製獨立調度所必須關鍵資源
    • 能夠和其餘線程共享進程資源
    • 若是線程的父進程死掉,則該線程死掉
    • 是「輕量級」的由於大可能是開銷在它的進程建立的時候已經完成了
  • 同一進程的線程間共享資源,致使:併發

    • 一個線程對於共享的系統資源所作的更改(例如關閉一個文件)將會被全部其餘的線程發現
    • 兩個具備相同值的指針指向相同的數據
    • 可能讀寫相同的內層位置,所以要求程序員進行顯式的同步

爲何使用線程

  • 在高性能計算的世界,使用線程的首要目的是實現潛在的程序性能的提高
  • 與建立和管理進程的花費相比,建立一個線程只須要較少的系統開銷。管理線程所須要的系統資源原少於管理進程異步

    舉例來講,下表是fork() 與 pthread_create()所花時間的對比。     工具

 

Platform fork() pthread_create()
real user sys real user sys
Intel 2.6 GHz Xeon E5-2670 (16 cores/node) 8.1 0.1 2.9 0.9 0.2 0.3
Intel 2.8 GHz Xeon 5660 (12 cores/node) 4.4 0.4 4.3 0.7 0.2 0.5
AMD 2.3 GHz Opteron (16 cores/node) 12.5 1.0 12.5 1.2 0.2 1.3
AMD 2.4 GHz Opteron (8 cores/node) 17.6 2.2 15.7 1.4 0.3 1.3
IBM 4.0 GHz POWER6 (8 cpus/node) 9.5 0.6 8.8 1.6 0.1 0.4
IBM 1.9 GHz POWER5 p5-575 (8 cpus/node) 64.2 30.7 27.6 1.7 0.6 1.1
IBM 1.5 GHz POWER4 (8 cpus/node) 104.5 48.6 47.2 2.1 1.0 1.5
INTEL 2.4 GHz Xeon (2 cpus/node) 54.9 1.5 20.8 1.6 0.7 0.9
INTEL 1.4 GHz Itanium2 (4 cpus/node) 54.5 1.1 22.2 2.0 1.2 0.6

  • 一個進程中的全部線程共享相同的地址空間。在不少狀況下線程間通訊比進程間通訊更高效和容易。性能

  • 線程應用與非線程應用相比,提供的潛在的性能提高和實際的優點主要經過如下幾種方法:

    • 經過I/O重疊CPU工做:
    • 優先/實時調用:更重要的任務能夠優先調用或者中斷低優先級的任務
    • 異步事件處理:服務不肯定頻率和交叉存取的事件的任務。舉例來講,一個web服務端程序能夠在和一個請求傳送數據的同時管理新到的請求

設計線程程序

並行編程

  • 設計並行程序須要考慮不少方面:
    • 使用什麼類型的並行編程模型
    • 問題分解
    • 負載平衡
    • 通訊
    • 數據依賴關係
    • 同步和競爭條件
    • 內存問題
    • I/O問題
    • ...
  • 本文將不對上述問題進行深刻的探討,不過,感興趣的能夠戳這裏:Introduction to Parallel Computing
  • 通常來說,一個程序想要發揮Pthread的優點,必須是能夠分離成獨立的能夠同時運行的子任務 如圖所示:
  • 適合使用Pthread的程序通常由以下性質:
    • 工做能夠被多任務同時執行或者數據能夠被同時操做
    • 潛在的長時間I/O等待阻塞
    • 必須響應異步事件
    • 一些工做比其餘的工做更重要(優先級中斷)
  • 一些常見的基於線程的程序模型:
    • Manager/worker:manager線程分配任務給其餘workers線程。
    • Pipeline:一個任務被分紅一系列的子任務,每一個子任務都被一個不一樣的線程有序併發的處理。相似汽車裝配線
    • Peer:有點相似Manager/worker,可是,在主線程創建其餘線程以後,就各自工做

共享內存模型:

  • 全部線程均可以訪問相同的全局,共享內存
  • 線程能夠由本身的私有數據
  • 程序員應該負責同步全局共享的數據的訪問 

線程安全

  • 線程安全:
  • 舉例,假設你的程序建立一些線程,每一個線程都調用相同的子程序:
    • 這個子程序訪問或者更改一個全局結構或者一個全局變量
    • 因爲每一個線程都調用這個子程序,因此它們可能同時嘗試修改這個全局結構或者全局變量
    • 若是這個子程序沒有使用某種同步方法來防止數據崩潰的話,這個程序就不是線程安全的 
相關文章
相關標籤/搜索