1. 程式人生 > >死磕 java執行緒系列之執行緒模型

死磕 java執行緒系列之執行緒模型

(2)執行緒模型有哪些?

(3)各語言使用的是哪種執行緒模型?

簡介

在Java中,我們平時所說的併發程式設計、多執行緒、共享資源等概念都是與執行緒相關的,這裡所說的執行緒實際上應該叫作“使用者執行緒”,而對應到作業系統,還有另外一種執行緒叫作“核心執行緒”。

使用者執行緒位於核心之上,它的管理無需核心支援;而核心執行緒由作業系統來直接支援與管理。幾乎所有的現代作業系統,包括 Windows、Linux、Mac OS X 和 Solaris,都支援核心執行緒。

最終,使用者執行緒和核心執行緒之間必然存在某種關係,本章我們一起來學習下建立這種關係常見的三種方法:多對一模型、一對一模型和多對多模型。

多對一模型

thread model

多對一執行緒模型,又叫作使用者級執行緒模型,即多個使用者執行緒對應到同一個核心執行緒上,執行緒的建立、排程、同步的所有細節全部由程序的使用者空間執行緒庫來處理。

優點:

  • 使用者執行緒的很多操作對核心來說都是透明的,不需要使用者態和核心態的頻繁切換,使執行緒的建立、排程、同步等非常快;

缺點:

  • 由於多個使用者執行緒對應到同一個核心執行緒,如果其中一個使用者執行緒阻塞,那麼該其他使用者執行緒也無法執行;

  • 核心並不知道使用者態有哪些執行緒,無法像核心執行緒一樣實現較完整的排程、優先順序等;

許多語言實現的協程庫基本上都屬於這種方式,比如python的gevent。

一對一模型

thread model

一對一模型,又叫作核心級執行緒模型,即一個使用者執行緒對應一個核心執行緒,核心負責每個執行緒的排程,可以排程到其他處理器上面。

優點:

  • 實現簡單【本篇文章由公眾號“彤哥讀原始碼”原創】;

缺點:

  • 對使用者執行緒的大部分操作都會對映到核心執行緒上,引起使用者態和核心態的頻繁切換;

  • 核心為每個執行緒都對映排程實體,如果系統出現大量執行緒,會對系統性能有影響;

Java使用的就是一對一執行緒模型,所以在Java中啟一個執行緒要謹慎。

多對多模型

thread model

多對多模型,又叫作兩級執行緒模型,它是博採眾長之後的產物,充分吸收前兩種執行緒模型的優點且儘量規避它們的缺點。

在此模型下,使用者執行緒與核心執行緒是多對多(m : n,通常m>=n)的對映模型。

首先,區別於多對一模型,多對多模型中的一個程序可以與多個核心執行緒關聯,於是程序內的多個使用者執行緒可以繫結不同的核心執行緒,這點和一對一模型相似;

其次,又區別於一對一模型,它的程序裡的所有使用者執行緒並不與核心執行緒一一繫結,而是可以動態繫結核心執行緒, 當某個核心執行緒因為其繫結的使用者執行緒的阻塞操作被核心排程讓出CPU時,其關聯的程序中其餘使用者執行緒可以重新與其他核心執行緒繫結執行。

所以,多對多模型既不是多對一模型那種完全靠自己排程的也不是一對一模型完全靠作業系統排程的,而是中間態(自身排程與系統排程協同工作),因為這種模型的高度複雜性,作業系統核心開發者一般不會使用,所以更多時候是作為第三方庫的形式出現。

優點:

  • 兼具多對一模型的輕量;

  • 由於對應了多個核心執行緒,則一個使用者執行緒阻塞時,其他使用者執行緒仍然可以執行;

  • 由於對應了多個核心執行緒,則可以實現較完整的排程、優先順序等;

缺點:

  • 實現複雜【本篇文章由公眾號“彤哥讀原始碼”原創】;

Go語言中的goroutine排程器就是採用的這種實現方案,在Go語言中一個程序可以啟動成千上萬個goroutine,這也是其出道以來就自帶“高併發”光環的重要原因。

後面講到Java中的ForkJoinPool的時候,我們會拿Go語言的PMG執行緒模型來對比講解。

總結

(1)執行緒分為使用者執行緒和核心執行緒;

(2)執行緒模型有多對一模型、一對一模型、多對多模型;

(3)作業系統一般只實現到一對一模型;

(4)Java使用的是一對一執行緒模型,所以它的一個執行緒對應於一個核心執行緒,排程完全交給作業系統來處理;

(5)Go語言使用的是多對多執行緒模型,這也是其高併發的原因,它的執行緒模型與Java中的ForkJoinPool非常類似;

(6)python的gevent使用的是多對一執行緒模型;

彩蛋

你所學過的語言都是使用的什麼執行緒模型呢?

推薦閱讀

1、死磕 java集合系列

2、死磕 java原子系列

3、死磕 java同步系列


歡迎關注我的公眾號“彤哥讀原始碼”,檢視更多原始碼系列文章, 與彤哥一起暢遊原始碼的海洋。

相關推薦

java執行系列執行模型

(2)執行緒模型有哪些? (3)各語言使用的是哪種執行緒模型? 簡介 在Java中,我們平時所說的併發程式設計、多執行緒、共享資源等概念都是與執行緒相關的,這裡所說的執行緒實際上應該叫作“使用者執行緒”,而對應到作業系統,還有另外一種執行緒叫作“核心執行緒”。 使用者執行緒位於核心之上,它的管理無需核心支援

java執行系列執行池深入解析——體系結構

(手機橫屏看原始碼更方便) 注:java原始碼分析部分如無特殊說明均基於 java8 版本。 簡介 Java的執行緒池是塊硬骨頭,對執行緒池的原始碼做深入研究不僅能提高對Java整個併發程式設計的理解,也能提高自己在面試中的表現,增加被錄取的可能性。 本系列將分成很多個章節,本章作為執行緒池的第一章將對

java執行系列執行池深入解析——生命週期

(手機橫屏看原始碼更方便) 注:java原始碼分析部分如無特殊說明均基於 java8 版本。 注:執行緒池原始碼部分如無特殊說明均指ThreadPoolExecutor類。 簡介 上一章我們一起重溫了下執行緒的生命週期(六種狀態還記得不?),但是你知不知道其實執行緒池也是有生命週期的呢?! 問題 (1)

java執行系列執行池深入解析——普通任務執行流程

(手機橫屏看原始碼更方便) 注:java原始碼分析部分如無特殊說明均基於 java8 版本。 注:執行緒池原始碼部分如無特殊說明均指ThreadPoolExecutor類。 簡介 前面我們一起學習了Java中執行緒池的體系結構、構造方法和生命週期,本章我們一起來學習執行緒池中普通任務到底是怎麼執行的。

java執行系列執行池深入解析——未來任務執行流程

(手機橫屏看原始碼更方便) 注:java原始碼分析部分如無特殊說明均基於 java8 版本。 注:執行緒池原始碼部分如無特殊說明均指ThreadPoolExecutor類。 簡介 前面我們一起學習了執行緒池中普通任務的執行流程,但其實執行緒池中還有一種任務,叫作未來任務(future task),使用它

java執行系列執行池深入解析——定時任務執行流程

(手機橫屏看原始碼更方便) 注:java原始碼分析部分如無特殊說明均基於 java8 版本。 注:本文基於ScheduledThreadPoolExecutor定時執行緒池類。 簡介 前面我們一起學習了普通任務、未來任務的執行流程,今天我們再來學習一種新的任務——定時任務。 定時任務是我們經常會用到的一

java concurrent包系列(一)從樂觀鎖、悲觀鎖到AtomicInteger的CAS演算法

前言 Java中有各式各樣的鎖,主流的鎖和概念如下: 這篇文章主要是為了讓大家通過樂觀鎖和悲觀鎖出發,理解CAS演算法,因為CAS是整個Concurrent包的基礎。 樂觀鎖和悲觀鎖 首先,java和資料庫中都有這種概念,他是一種從執行緒同步的角度上看的一種廣義上的概念: 悲觀鎖:悲觀的認為自己在使用資料的

java concurrent包系列(三)基於ReentrantLock理解AQS的條件佇列

基於Codition分析AQS的條件佇列 前言 上一篇我們講了AQS中的同步佇列佇列,現在我們研究一下條件佇列。 在java中最常見的加鎖方式就是synchorinzed和Reentrantlock,我們都說Reentrantlock比synchorinzed更加靈活,其實就靈活在Reentrantlock中

java concurrent包系列(五)基於AQS的條件佇列把LinkedBlockingQueue“扒光”

LinkedBlockingQueue的基礎 LinkedBlockingQueue是一個基於連結串列的阻塞佇列,實際使用上與ArrayBlockingQueue完全一樣,我們只需要把之前烤雞的例子中的Queue物件替換一下即可。如果對於ArrayBlockingQueue不熟悉,可以去看看https://

java concurrent包系列(六)基於AQS解析訊號量Semaphore

Semaphore 之前分析AQS的時候,內部有兩種模式,獨佔模式和共享模式,前面的ReentrantLock都是使用獨佔模式,而Semaphore同樣作為一個基於AQS實現的併發元件,它是基於共享模式實現的,我們先看看它的使用場景 Semaphore共享鎖的基本使用 假設有20個人去銀行櫃面辦理業務,

java執行系列建立執行的8種方式

問題 (1)建立執行緒有哪幾種方式? (2)它們分別有什麼運用場景? 簡介 建立執行緒,是多執行緒程式設計中最基本的操作,彤哥總結了一下,大概有8種建立執行緒的方式,你知道嗎? 繼承Thread類並重寫run()方法 public class CreatingThread01 extends Thread

java執行系列自己動手寫一個執行

歡迎關注我的公眾號“彤哥讀原始碼”,檢視更多原始碼系列文章, 與彤哥一起暢遊原始碼的海洋。 (手機橫屏看原始碼更方便) 問題 (1)自己動手寫一個執行緒池需要考慮哪些因素? (2)自己動手寫的執行緒池如何測試? 簡介 執行緒池是Java併發程式設計中經常使用到的技術,那麼自己如何動手寫一個執行緒池呢?本

java執行系列自己動手寫一個執行池(續)

(手機橫屏看原始碼更方便) 問題 (1)自己動手寫的執行緒池如何支援帶返回值的任務呢? (2)如果任務執行的過程中丟擲異常了該

java執行系列終篇

(手機橫屏看原始碼更方便) 簡介 執行緒系列我們基本就學完了,這一個系列我們基本都是圍繞著執行緒池在講,其實關於執行緒還有很多東西可以講,後面有機會我們再補充進來。當然,如果你有什麼好的想法,也可以公從號右下角聯絡我。 重要知識點 直接上圖,看著這張圖我相信你能夠回憶起很多東西,也可以看著這張圖來自己提

Java併發】-----J.U.CAQS:阻塞和喚醒執行

此篇部落格所有原始碼均來自JDK 1.8 線上程獲取同步狀態時如果獲取失敗,則加入CLH同步佇列,通過通過自旋的方式不斷獲取同步狀態,但是在自旋的過程中則需要判斷當前執行緒是否需要阻塞,其主要方法在acquireQueued(): if (sho

【紮實基本功】Java基礎教程系列執行

1. 多執行緒的概念 1.1 程序、執行緒、多程序的概念 程序:正在進行中的程式(直譯)。 執行緒是程式執行的一條路徑, 一個程序中可以包含多條執行緒。 一個應用程式可以理解成就是一個程序。 多執行緒併發執行可以提高程式的效率, 可以同時完成多項工作。 1.

Java執行系列--“JUC執行池”01 執行池架構

概要 前面分別介紹了”Java多執行緒基礎”、”JUC原子類”和”JUC鎖”。本章介紹JUC的最後一部分的內容——執行緒池。內容包括: 執行緒池架構圖 執行緒池示例 執行緒池架構圖 執行緒池的架構圖如下: 1、Executor

Java執行系列--“JUC執行池”05 執行池原理(四)

概要 本章介紹執行緒池的拒絕策略。內容包括: 拒絕策略介紹 拒絕策略對比和示例 拒絕策略介紹 執行緒池的拒絕策略,是指當任務新增到執行緒池中被拒絕,而採取的處理措施。 當任務新增到執行緒池中之所以被拒絕,可能是由於:第一,執行緒池異常關閉。第二,任務數量

Java 併發程式設計系列帶你瞭解多執行

早期的計算機不包含作業系統,它們從頭到尾執行一個程式,這個程式可以訪問計算機中的所有資源。在這種情況下,每次都只能執行一個程式,對於昂貴的計算機資源來說是一種嚴重的浪費。 作業系統出現後,計算機可以執行多個程式,不同的程式在單獨的程序中執行。作業系統負責為各個獨

java執行系列模式|第一篇-Guarded Suspension pattern

Guarded Suspension pattern模式 作者注:該系列文章基於《java執行緒設計模式》撰寫,只用於學習和交流。 定義:多執行緒執行,當前執行緒沒有達到警戒條件時,執行緒會進入等待直到