歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> 關於Linux

Linux多線程實踐(一)線程基本概念和理論

線程概念

在一個程序裡的一個執行路線就叫做線程(thread)。更准確的定義是:線程是“一個進程內部的控制序列/指令序列”;

對於每個進程至少有一個執行線程;

 

進程 VS. 線程

1.進程是資源分配(進程需要參與資源的競爭)的基本單位,而線程是處理器調度(程序執行)的最小單位;

2.線程共享進程數據,但也擁有自己的一部分數據,如 線程ID、一組寄存器、堆棧、errno(錯誤代碼)、信號狀態、優先級等;

3.一個進程內部的線程可以共享資源,如代碼段、數據段、打開文件和信號等(如下圖所示)。

\

 

fork VS. pthread_create

當一個進程執行一個fork調用的時候,會創建出進程的一個新拷貝,新進程將擁有它自己的變量和它自己的PID。這個新進程的運行時間是獨立的,它在執行時幾乎完全獨立於創建它的進程(其父進程).

 

而在進程裡面創建一個新線程的時候,新的執行線程會擁有自己的堆棧(因此也就有自己的局部變量),但要與它的創建者共享全局變量、文件描述符、信號處理器和當前的工作目錄狀態(如下圖:最上面的三項code,data,files是共享的!); (所以FTP服務器是不能使用多線程實現的,因為一個線程引起的工作目錄的改變,會影響到其他線程。)

\

 

線程的優點

創建一個新線程的代價要比創建一個新進程小得多(因此有時thread被稱為輕型進程)

與進程之間的切換相比,線程之間的切換需要操作系統做的工作要少很多(提高了並發程度)

線程占用的資源要比進程少很多

能充分利用多處理器的可並行數量(如果是2CPU狀態,多線程可以充分競爭到CPU,利用可並行)

在等待慢速I/O操作結束的同時,程序可執行其他的計算任務

計算密集型應用,為了能在多處理器系統上運行,將計算分解到多個線程中實現

I/O密集型應用,為了提高性能,將I/O操作重疊。線程可以同時等待不同的I/O操作

 

線程缺點

性能損失:一個很少被外部事件阻塞的計算密集型線程往往無法與共它線程共享同一個處理器。如果計算密集型線程的數量比可用的處理器多,那麼可能會有較大的性能損失,這裡的性能損失指的是增加了額外的同步和調度開銷,而可用的資源不變。

健壯性降低:編寫多線程需要更全面更深入的考慮,在一個多線程程序裡,因時間分配上的細微偏差或者因共享了不該共享的變量而造成不良影響的可能性是很大的,因此如果一個進程中的一個線程崩潰可能會造成其他線程的崩潰!換句話說線程之間是缺乏保護的。

缺乏訪問控制:進程是訪問控制的基本粒度,如在一個線程中調用某些OS函數會對整個進程造成影響,比如在一個線程中更改了當前工作目錄,則其他線程也隨之改變。

編程難度提高:編寫與調試一個多線程程序比單線程程序困難得多;

 

線程調度競爭范圍

操作系統提供了各種模型,用來調度應用程序創建的線程。這些模型之間的主要不同是,在競爭系統資源(特別是CPU時間)時,線程調度競爭范圍(thread-scheduling contention scope)不一樣:

1.進程競爭范圍(process contention scope):各個線程在同一進程競爭“被調度的CPU時間”(但不直接和其他進程中的線程競爭)。

2.系統競爭范圍(system contention scope):線程直接和“系統范圍”內的其他線程競爭。

 

多線程模型

1. N:1[將多個用戶級線程映射到一個內核級線程,早期OS的線程實現方式]

“線程實現”建立在“進程控制”機制之上,由用戶空間的程序庫來管理。OS內核完全不知道線程信息。這些線程稱為用戶空間線程。

這些線程工作在“進程競爭范圍”;

\

優點:在N:1線程模型中,內核不干涉線程的任何生命活動,也不干涉同一進程中的線程環境切換。線程管理實在用戶空間進行的,因而效率比較高;

缺點:

(1)一個進程中的多個線程只能調度到一個CPU,這種約束限制了可用的並行總量。

(2)如果某個線程執行了一個“阻塞式”操作(如read),那麼,進程中的所有線程都會阻塞,直至那個操作結束。為此,一些線程的實現是為這些阻塞式函數提供包裝器,用非阻塞版本替換這些系統調用,以消除這種限制。

 

2. 1:1[將每個用戶級線程映射到一個內核級線程]

在1:1核心線程模型中,應用程序創建的每一個線程都由一個核心線程直接管理。

OS內核將每一個核心線程都調到系統CPU上,因此,所有線程都工作在“系統競爭范圍”。

優點:當一個線程被阻塞後,允許另一個線程繼續運行,提高了並發的能力,然而這種線程的創建與調度由內核完成,因此這種線程的系統開銷比較大(但一般來說,比進程開銷小)

 

\

3. N:M[將N個用戶級線程映射到M個內核級線程上,要求N>=M,當代的Posix線程(即當前Linux所采用的線程模型)]

N:M線程模型提供了兩級控制,將用戶線程映射為系統的可調度體以實現並行LWP,這個可調度體稱為輕量級進程(LWP:lightweight process),LWP再一一映射到核心線程.[thread -> LWP -> 核心線程(參與調度)]

\

輕量級進程是內核支持的用戶線程,是內核線程的一種抽象對象。每個線程擁有一個或多個輕量級線程,而每個輕量級線程分別被綁定在一個內核線程上。

N:M線程模型克服了多對一模型的並發度不高的缺點,又克服了一對一模型的一個用戶線程占用太多內核級線程,開銷太大的缺點.又擁有多對一,一對一模型的各自的優點,可謂集兩家之長;

 

線程實現分類:

(1)用戶級線程

用戶級線程主要解決的是上下文切換的問題,它的調度算法和調度過程全部由用戶自行選擇決定,在運行時不需要特定的內核支持。在這裡,操作系統往往會提供一個用戶空間的線程庫,該線程庫提供了線程的創建、調度和撤銷等功能,而內核仍然僅對進程進行管理。 如果一個進程中的某一個線程調用了一個阻塞的系統調用函數,那麼該進程包括該進程中的其他所有線程也同時被阻塞。這種用戶級線程的主要缺點是在一個進程中的多個線程的調度中無法發揮多處理器的優勢。

 

(2)內核級線程

這種線程允許不同進程中的線程按照同一相對優先調度方法進行調度,這樣就可以發揮多處理器的並發優勢。

現在大多數系統都采用用戶級線程與核心級線程並存的方法。一個用戶級線程可以對應一個或幾個核心級線程,也就是“一對一”或“多對一”模型。這樣既可滿足多處理機系統的需要,也可以最大限度地減少調度開銷。

 

總結:

使用線程機制大大加快上下文切換速度而且節省很多資源。但是因為在用戶態和內核態均要實現調度管理,所以會增加實現的復雜度和引起優先級翻轉的可能性。一個多線程程序的同步設計與調試也會增加程序實現的難度.

 

Copyright © Linux教程網 All Rights Reserved