日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Go语言的并发

發布時間:2023/12/20 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Go语言的并发 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

Go是一種靜態強類型,``編譯型,并發型并且具有垃圾回收的編程語言

以上摘自維基百科Go語言的介紹.

從誕生之初,Go語言就備受矚目,Google的支持,強大的開發團隊,面向現代處理器的編程優化,一切都預示go語言的美好前景.

筆者的主力語言是Java,最近也抽空研究了一下Go語言,查到的資料中描述了很多Go的強大特性,這些特性都很誘人,但是還不足以稱為語言的基礎,本文將只闡述Go的并發特性.

Go語言的高并發(concurrency)

concurrency(并發) is not parallelism(并行)

Concurrency is about?dealing with?lots of things at once. Parallelism is about?doing?lots of things at once.

詳見Concurrency is not parallelism

Go的并發基礎: goroutine

A?goroutine?is a lightweight thread managed by the Go runtime.

goroutine是由Go runtime管理的比輕量級線程(LWP)更輕量的線程(姑且這么叫吧).它的開銷很小,可以輕易的同時啟動成千上萬個goroutine,設想一下Java中開啟10個線程的消耗在Go語言中可以用來開啟100甚至1000個goroutine,顯然Go語言的運行效率會更高,要明白goroutine到底是什么,讓我們先從線程開始講起

從線程開始

線程的基礎概念

線程分為三類kernel threads, user threads, and fibers

kernel threads 內核線程

kernel thread是由操作系統內核支持的線程,也是基本意義上的線程,kernel thread切換由內核完成.一般程序不會直接使用kernel thread,而是使用kernel thread的一種高級接口-輕量級進程(Light Weight Process)一個LWP對應于一個kernel thread.

user threads 用戶線程

user thread指不需要內核支持而在用戶程序中實現的線程,它不依賴于內核,用戶自己實現user thread的創建,同步,調度,管理等功能.這里一個LWP對應多個user thread,簡單點說 一個進程擁有多個LWP,一個LWP又擁有多個user thread.,這里的用戶一般指的是編程語言

fiber 混合

兩者的混合,折中方案,不多說

它們的優缺點都是什么

對于kernel thread和user thread,站在編程語言的角度來看,都有什么優缺點

kernel thread

kernel thread的優點:

  • kernel thread由內核管理,使用kernel thread時調用LWP的函數即可,對于編程語言來說實現簡單
  • 對于多核處理器,內核可以將線程調度到其他核心上運行,可以充分利用多核的優勢
  • kernel thread的缺點:

  • kernel thread的管理需要系統調用,而系統調用需要在用戶態和內核態切換,代價很高
  • 由于LWP和kernel thread是1:1的,每個LWP都要消耗一部分內核資源,這也限制了kernel thread的數量
  • user thread

    user thread的優點:

  • user thread的切換由編程語言控制,不涉及內核,也就很少需要內核態和用戶態的切換,效率高
  • 一個LWP對應多個user thread,因此user thread的數量要大大超過LWP.意味著更高的并發
  • user thread的缺點:

  • 需要自己實現user thread的管理,很困難
  • user thread是由用戶管理的,而內核只能控制到LWP,那么在多核處理器下,user thread只能在某個核心上的某個線程上跑,無法充分利用多核優勢
  • 如果某個user thread由于某些原因被阻塞,那么這個LWP上的所有user thread都被阻塞了
  • 綜上所述,kernel thread由內核控制,使用簡單但是效率不夠高.user thread由用戶(編程語言)實現,效率很高,但是實現起來比較復雜. 在講Go語言使用了哪種線程模式之前,先來看下Java

    Java為什么從user thread轉為kernel thread?

    JDK1.2時使用的還是user thread,Java的開發團隊稱之為Green Thread,為什么后面切換到了kernel thread呢? 查閱資料后在這里找到了原因,sco的說明 大致有一下兩點原因

  • Java開發團隊在實現Green Threads時,為了達到非阻塞IO,對系統調用做了封裝,但是某些JNI調用會打破這個封裝,導致一些很嚴重的問題
  • Green Threads無法充分利用多核優勢,原因同user thread的缺點2
  • 還有以下說明

    here is a significant processing overhead for the JVM to keep track of thread states and swap between them, so green thread mode has been deprecated and removed from more recent Java implementations

    總體來看是Java開發團隊由于時代背景,user thread的實現有缺陷,因此才切換到kernel thread的線程模式

    Go使用了哪個線程模型

    Go使用了user thread的線程模型,在Go中稱之為goroutine,這是Go稱為并發型語言的基礎. Go語言中有邏輯處理器(Logic Processor)的概念,通過它完成user thread的調度.

    下面看下goroutine如何解決user thread的缺陷

    如何處理阻塞的user thread

    下圖截取自 ,可以看到當goroutine執行了阻塞的系統調用后,調度器將這個LWP與LP分離,并創建一個新的LWP為這個LP提供服務

    如何充分利用多核

    參見Fork/Join中的工作竊取算法,TODO

    再談內存模型

    關于內存模型,參見共享內存和消息傳遞,總結一下

    共享內存的通信是隱式的,線程之間通過寫-讀內存中的公共狀態來隱式通信,而線程之間的同步是顯式的,必須在代碼中寫好同步邏輯. 消息傳遞的通信是顯式的,線程之間通過明確的發送消息來通信,由于收消息肯定在發消息之后,因此線程之間的同步是隱式的

    目前的語言大都共享內存,為什么不用消息傳遞?以前的編程語言大都使用了kernel thread模式,而在kernel thread之間傳遞消息消耗太大,因此只能選擇代碼編寫更麻煩的共享內存模型

    Go使用了哪種內存模型

    消息傳遞!,Go使用了user thread的線程模式.消息傳遞的消耗不再成為問題,自然要選擇更有利于并發的消息傳遞模型,在Go中,消息傳遞主要通過chan這個結構完成chan即通道.類似于Java nio中通道的概念.goroutine通過在chan中發送/讀取消息實現同步.

    結語

    本文簡要說明了Go語言高并發的實現基礎,可以看到Go的高并發是語言設計時天生的優勢.


    • 命令式編程 vs 聲明式編程
    • 線程-wikipedia
    • 線程的實現

    總結

    以上是生活随笔為你收集整理的Go语言的并发的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。