日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

1.概述

在本文中,我們將討論為建立高度并發的應用程序而逐漸建立的一些設計原理和模式。

但是,值得注意的是,設計并發應用程序是一個廣泛而復雜的主題,因此,沒有任何教程可以聲稱對它的處理是詳盡無遺的。我們這里將介紹一些常用的技巧!

2.并發基礎

在繼續進行之前,先來了解基礎知識。首先,我們必須闡明我們對所謂的并發程序的理解:如果同時進行多個計算,則我們將程序稱為并發程序。

現在,請注意,我們已經提到了計算是同時發生的,也就是說,它們是同時進行的。但是,它們可能同時執行或不同時執行,了解差異是很重要的,因為同時執行的計算稱為parallel

2.1 如何創建并發模塊?

了解我們如何創建并發模塊很重要。有很多選項,但我們將在此處重點介紹兩個流行的選擇:

  • 進程:進程是正在運行的程序的實例,該程序與同一計算機中的其他進程隔離。機器上的每個進程都有自己獨立的時間和空間。因此,通常不可能在進程之間共享內存,并且它們必須通過傳遞消息進行通信。
  • 線程:另一方面,線程只是進程的一部分,一個程序中可以有多個線程共享同一內存空間。但是,每個線程都有唯一的堆棧和優先級。線程可以是本地線程(由操作系統本地調度)或綠色(由運行時庫調度)。

2.2 并發模塊如何交互?

如果并發模塊不必通信,這是非常理想的,但是通常不是這種情況。這產生了兩種并發編程模型:

  • 共享內存:在此模型中,并發模塊通過在內存中讀寫共享對象進行交互。這通常導致并發計算的交錯,從而導致競爭條件。因此,它可以不確定地導致不正確的狀態。
【實用技巧篇】高并發應用程序的設計原理和模式

 

  • 消息傳遞:在此模型中,并發模塊通過通過通信通道相互傳遞消息來進行交互。在這里,每個模塊順序處理傳入的消息。由于沒有共享狀態,因此編程相對容易一些,但這仍然無法擺脫競爭條件!
【實用技巧篇】高并發應用程序的設計原理和模式

 

2.3 并發模塊如何執行?

自從摩爾定律在處理器的時鐘速度方面碰壁以來已經有一段時間了。取而代之的是,由于必須增長,因此我們開始將多個處理器打包到同一芯片上,通常稱為多核處理器。但是,聽到具有32個以上內核的處理器并不罕見。

現在,我們知道單個內核一次只能執行一個線程或一組指令。但是,進程和線程的數量可以分別為數百和數千。那么,它如何真正起作用?這是操作系統為我們模擬并發的地方。操作系統通過時間分片來實現這一點-這實際上意味著處理器會頻繁地,不可預測地且不確定地在線程之間切換。

3.并行編程中的問題

在很大程度上,我們在并行編程方面的經驗涉及將本機線程與共享內存一起使用。因此,我們將專注于由此產生的一些常見問題:

  • 互斥(同步基元):交織線程需要對共享狀態或內存具有獨占訪問權限,以確保程序的正確性。共享資源的同步是一種實現互斥的流行方法。有幾種同步原語可供使用-例如,鎖,監視器,信號燈或互斥鎖。但是,互斥編程很容易出錯,通常會導致性能瓶頸。與死鎖和活鎖相關的問題有很多討論的。
  • 上下文切換(重量級線程):每個操作系統都有本機(盡管有所不同)對進程和線程等并發模塊的支持。如討論的那樣,操作系統提供的基本服務之一是調度線程,以便通過時間分片在有限數量的處理器上執行。現在,這實際上意味著線程經常在不同狀態之間切換。在此過程中,需要保存并恢復其當前狀態。這是一項耗時的活動,直接影響整體吞吐量。

4.高并發設計模式

現在,我們了解了并發編程的基礎知識以及其中的常見問題,是時候了解一些避免這些問題的常見模式了。我們必須重申,并發編程是一項艱巨的任務,需要大量經驗。因此,遵循某些已建立的模式可以使任務更容易。

4.1 基于Actor的并發

我們將針對并發編程討論的第一個設計稱為Actor模型。這是并行計算的數學模型,基本上將一切都視為參與者。參與者可以相互傳遞消息,并且響應消息可以做出本地決策。這是由卡爾·休伊特(Carl Hewitt)首次提出的,并啟發了許多編程語言。

Scala用于并發編程的主要構造是參與者。Actor是Scala中的普通對象,我們可以通過實例化Actor類來創建。此外,Scala Actors庫提供了許多有用的actor操作:

class myActor extends Actor {
    def act() {
        while(true) {
            receive {
                // Perform some action
            }
        }
    }
}

在上面的示例中,在無限循環內對receive方法的調用將使actor掛起,直到消息到達為止。到達后,郵件將從參與者的郵箱中刪除,并采取了必要的措施。

【實用技巧篇】高并發應用程序的設計原理和模式

 

actor模型消除了并發編程的基本問題之一-------共享內存。參與者通過消息進行通信,并且每個參與者依次處理其專用郵箱中的消息。但是,我們通過線程池執行角色,而且我們已經看到,本地線程可能是重量級的,因此數量有限。

當然,這里還有其他模式可以為我們提供幫助,稍后將介紹這些模式!

4.2 基于事件的并發

基于事件的設計明確解決了本機線程生成和操作成本高昂的問題。基于事件的設計之一是事件循環。事件循環與事件提供程序和一組事件處理程序一起使用。在這種設置中,事件循環在事件提供程序上阻塞,并在到達時將事件調度到事件處理程序

基本上,事件循環不過是事件分配器!事件循環本身可以僅在單個本機線程上運行。那么,事件循環中到底發生了什么?讓我們來看一個非常簡單的事件循環的偽代碼作為示例:

while(true) {
    events = getEvents();
    for(e in events)
        processEvent(e);
}

基本上,我們的事件循環所要做的就是不斷尋找事件,并在發現事件后對其進行處理。該方法確實很簡單,但可以從事件驅動的設計中受益。

使用此設計構建并發應用程序可為應用程序提供更多控制。而且,它消除了多線程應用程序的一些典型問題,例如死鎖。

【實用技巧篇】高并發應用程序的設計原理和模式

 

JAVAScript實現事件循環以提供異步編程。它維護一個調用堆棧以跟蹤要執行的所有功能。它還維護一個事件隊列,用于發送新功能進行處理。事件循環不斷檢查調用堆棧,并從事件隊列中添加新功能。所有異步調用都會分派到通常由瀏覽器提供的Web API。

事件循環本身可以在單個線程上運行,但是Web API提供了單獨的線程。

4.3 非阻塞算法

在非阻塞算法中,一個線程的掛起不會導致其他線程的掛起。我們已經看到,我們的應用程序中只能有數量有限的本機線程。現在,阻塞在線程上的算法明顯降低了吞吐量, 并阻止了我們構建高度并發的應用程序。

非阻塞算法始終使用底層硬件提供的比較交換原子原語。這意味著硬件將比較存儲位置的內容與給定值,并且只有它們相同時,才會將值更新為新的給定值。這看起來很簡單,但實際上為我們提供了一個原子操作,否則將需要同步。

這意味著我們必須編寫使用此原子操作的新數據結構和庫。這為我們提供了多種語言的大量免等待和免鎖實現。Java具有幾種非阻塞數據結構,例如AtomicBoolean,AtomicInteger,AtomicLong和AtomicReference。

考慮一個有多個線程試圖訪問相同代碼的應用程序:

boolean open = false;
if(!open) {
    // Do Something
    open=false;
}

顯然,上面的代碼不是線程安全的,并且它在多線程環境中的行為可能是不可預測的。我們的選擇是將這段代碼與鎖同步,或者使用原子操作:

AtomicBoolean open = new AtomicBoolean(false);
if(open.compareAndSet(false, true) {
    // Do Something
}

如我們所見,使用像AtomicBoolean這樣的非阻塞數據結構可以幫助我們編寫線程安全的代碼,而不會沉迷于鎖的弊端!

5.支持編程語言

我們已經看到,可以通過多種方式構造并發模塊。盡管編程語言確實有所作為,但主要是底層操作系統如何支持該概念。但是,由于本機線程支持的基于線程的并發在可伸縮性方面遇到了新的障礙,因此我們始終需要新的選擇。

我們可以使用的一種解決方案是綠色線程。綠色線程是由運行時庫調度的線程,而不是由底層操作系統本地調度的線程。盡管這并不能解決基于線程的并發中的所有問題,但在某些情況下,它肯定可以為我們提供更好的性能。

現在,除非我們選擇使用的編程語言支持綠色線程,否則使用綠色線程并非易事。并非每種編程語言都具有此內置支持。同樣,我們可以通過不同的編程語言以非常獨特的方式來實現我們所謂的綠色線程。讓我們來看一些可用的選項。

5.1 Go中的Goroutines

Go編程語言中的Goroutine 是輕量級線程。它們提供可以與其他功能或方法同時運行的功能或方法。Goroutines 非常便宜,因為它們從開始只占用幾千字節的堆棧大小

最重要的是,goroutines與較少數量的本機線程復用。此外,goroutine使用通道相互通信,從而避免了對共享內存的訪問。我們幾乎獲得了所需的一切,然后猜測-什么都不做!

5.2 Erlang中的進程

在Erlang中,每個執行線程稱為一個進程。但是,這與我們到目前為止討論的過程不太一樣!Erlang進程重量輕,內存占用少,并且創建和處理速度快,調度開銷低。

在幕后,Erlang進程不過是運行時為之調度的功能。而且,Erlang進程不共享任何數據,它們通過消息傳遞相互通信。這就是為什么我們首先稱這些“過程”的原因!

5.3 Java中的Fiber(提案)

Java并發的故事一直在不斷發展。Java確實從一開始就對綠色線程(至少對Solaris操作系統)提供了支持。但是,由于障礙超出了本教程的范圍,因此已停止使用。

從那時起,Java中的并發全部與本地線程有關,以及如何巧妙地使用它們!但是出于顯而易見的原因,我們可能很快就會在Java中有了一個新的并發抽象,稱為光纖。Project Loom建議將延續與纖維一起引入,這可能會改變我們用 Java 編寫并發應用程序的方式

這只是對不同編程語言中可用功能的簡要介紹。其他編程語言還嘗試了更多有趣的方式來處理并發。

此外,值得注意的是,在設計高度并發的應用程序時,上一節中討論的設計模式與編程語言對類似綠線程的抽象的支持的組合可能會非常強大。

6.高并發應用

實際應用程序通常具有多個組件,這些組件通過導線相互交互。我們通常通過Internet對其進行訪問,它包含多種服務,例如代理服務,網關,Web服務,數據庫,目錄服務和文件系統。

在這種情況下,我們如何確保高并發性?讓我們探索其中的一些層以及構建高度并發應用程序所具有的選項。

構建高并發應用程序的關鍵是使用此處討論的一些設計概念。我們需要為工作選擇合適的軟件-----已經結合了其中一些實踐的軟件。

6.1 網頁層

Web通常是用戶請求到達的第一層,因此在此處不可避免地需要進行高并發性設置。讓我們看看其中的一些選項:

  • Node(也稱為NodeJS或Node.js)是基于Chrome的V8 JavaScript引擎構建的開源,跨平臺JavaScript運行時。在處理異步I / O操作時,Node工作得很好。Node之所以如此出色,是因為它在單個線程上實現了一個事件循環。借助回調的事件循環可異步處理所有阻塞操作,例如I / O。
  • Nginx一個開放源代碼的Web服務器,除其他用法外,我們通常將用作反向代理。nginx提供高并發性的原因是它使用了異步的,事件驅動的方法。nginx在一個線程中與主進程一起運行。主流程維護執行實際處理的工作流程。因此,工作進程同時處理每個請求。

6.2 應用層

在設計應用程序時,有多種工具可幫助我們構建高并發性,先檢查一下其中一些可用的庫和框架:

  • Akka用Scala編寫的工具包,用于在JVM上構建高度并發和分布式的應用程序。Akka處理并發的方法基于我們前面討論的參與者模型。Akka在參與者和基礎系統之間創建了一層。該框架處理創建和調度線程,接收和調度消息的復雜性。
  • Project Reactor 是一個反應式庫,用于在JVM上構建非阻塞應用程序。它基于Reactive Streams規范,專注于有效的消息傳遞和需求管理(背壓)。反應堆操作員和調度程序可以維持較高的消息吞吐率。幾個流行的框架提供了Reactor的實現,包括Spring WebFlux和RSocket。
  • Netty是一個異步的,事件驅動的網絡應用程序框架。我們可以使用Netty開發高度并發的協議服務器和客戶端。Netty利用了 NIO,它是Java API的集合,可通過緩沖區和通道提供異步數據傳輸。它為我們提供了多個優勢,例如更好的吞吐量,更低的延遲,更少的資源消耗以及最小化不必要的內存復制

6.3 資料層

沒有數據就沒有完整的應用程序,數據來自持久性存儲。當我們討論有關數據庫的高并發性時,大多數重點仍放在NoSQL系列上。這主要是由于NoSQL數據庫可以提供線性可伸縮性,但是在關系型變量中卻很難實現。讓我們看一下數據層的兩個流行工具:

  • Cassandra是一個免費的開源NoSQL分布式數據庫,可在商品硬件上提供高可用性,高可伸縮性和容錯能力。但是,Cassandra不提供跨越多個表的ACID事務。因此,如果我們的應用程序不需要強一致性和事務性,那么我們可以受益于Cassandra的低延遲操作。
  • Kafka是一個分布式流媒體平臺。Kafka將記錄流存儲在稱為主題的類別中。它可以為記錄的生產者和使用者提供線性水平可伸縮性,同時提供高可靠性和耐用性。分區,副本和代理是它提供大規模分布式并發的一些基本概念。

6.4 緩存層

現代世界中沒有任何旨在實現高并發性的Web應用程序能夠承受每次訪問數據庫的負擔。這就讓我們選擇了一個緩存-----最好是可以支持我們高度并發的應用程序的內存中緩存:

  • Hazelcast 是一個分布式,云友好的,內存中的對象存儲和計算引擎,支持多種數據結構,如地圖,設置,列表,多重映射, RingBuffer和 HyperLogLog。它具有內置的復制功能,并提供高可用性和自動分區。
  • redis 是一種內存數據結構存儲,我們主要將其用作緩存。它提供了一個內存鍵值數據庫,具有可選的持久性。支持的數據結構包括字符串,哈希,列表和集合。Redis具有內置的復制功能,并提供高可用性和自動分區。如果我們不需要持久性,Redis可以為我們提供功能豐富,網絡化的內存中緩存,并具有出色的性能。

當然,在我們追求構建高度并發的應用程序時,我們幾乎沒有涉及任何可用的內容。重要的是要注意,除可用軟件外,我們的要求還應指導我們創建適當的設計。這些選項中的某些選項可能適用,而其他選項可能不合適。

而且,別忘了還有更多可用的選項可能更適合我們的要求。

7.結論

在本文中,我們討論了并發編程的基礎。我們了解了并發的一些基本方面及其可能導致的問題。此外,我們演示了一些設計模式,這些模式可以幫助我們避免并發編程中的典型問題。

最后,我們介紹了一些可用于構建高度并行的端到端應用程序的框架,庫和軟件。

讀者福利

分享一份自己整理好的Java學習資料,里面包含了:分布式架構、高可擴展、高性能、高并發、Jvm性能調優、Spring,MyBatis,Nginx源碼分析,Redis,ActiveMQ、、Mycat、Netty、Kafka、MySQL、Zookeeper、Tomcat、Docker、Dubbo、Nginx等多個知識點高級進階干貨

 

【實用技巧篇】高并發應用程序的設計原理和模式

 

 

【實用技巧篇】高并發應用程序的設計原理和模式

 

 

【實用技巧篇】高并發應用程序的設計原理和模式

 

 

 

分享到:
標簽:并發 應用程序
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定