摘要:一并發(fā)和并行并發(fā)是同一時間應(yīng)對多件事情的能力并行是同一時間做多件事情的能力。用并發(fā)的目的,不僅僅是為了讓程序并行運行從而發(fā)揮多核的優(yōu)勢。函數(shù)式編程函數(shù)式編程日漸重要的原因之一,是其對并發(fā)編程和并行編程提供了良好的支持。
一、并發(fā)和并行:
并發(fā)是同一時間應(yīng)對(dealing with)多件事情的能力;
并行是同一時間做(doing)多件事情的能力。
二、并行架構(gòu):
位級并行,32位計算機的運行速度比8位計算機更快,因為并行,對于32位數(shù)的加法,8位計算機必須進行多次8位計算,而32位計算機可以一步完成,即并行的處理32位的4字節(jié)。
指令級(instruction-level)并行,程序員通常可以不關(guān)心處理器內(nèi)部并行的細(xì)節(jié),因為盡管處理器內(nèi)部的并行度很高,但是經(jīng)過精心設(shè)計,從外部看上去所有處理都像是串行的。
數(shù)據(jù)級(data)并行,數(shù)據(jù)級并行(也稱為“單指令多數(shù)據(jù)”,SIMD)架構(gòu),可以并行地在大量數(shù)據(jù)上施加同一操作。這并不適合解決所有問題,但在適合的場景卻可以大展身手。
任務(wù)級(task-level)并行,終于來到了大家所認(rèn)為的并行形式——多處理器。從程序員的角度來看,多處理器架構(gòu)最明 顯的分類特征是其內(nèi)存模型(共享內(nèi)存模型或分布式內(nèi)存模型)。
對于共享內(nèi)存的多處理器系統(tǒng),每個處理器都能訪問整個內(nèi)存,處理器之間的通信主要通過內(nèi)存進行。
對于分布式內(nèi)存的多處理器系統(tǒng),每個處理器都有自己的內(nèi)存,處理器之間的通信主要通過網(wǎng)絡(luò)進行。
用并發(fā)的目的,不僅僅是為了讓程序并行運行從而發(fā)揮多核的優(yōu)勢。若正確使用并發(fā),程序還將獲得以下優(yōu)點:及時響應(yīng)、高效、容錯、簡單。
注意:不應(yīng)該在產(chǎn)品代碼上,使用Thread類等底層服務(wù)。
三、七個模型
1、線程與鎖:線程與鎖模型有很多眾所周知的不足,但仍是其他模型的技術(shù)基礎(chǔ),也是很多并 發(fā)軟件開發(fā)的首選。 2、函數(shù)式編程:函數(shù)式編程日漸重要的原因之一,是其對并發(fā)編程和并行編程提供了良好的支 持。函數(shù)式編程消除了可變狀態(tài),所以從根本上是線程安全的,而且易于并行執(zhí)行。 3、Clojure之道——分離標(biāo)識與狀態(tài):編程語言Clojure是一種指令式編程和函數(shù)式編程的混搭方 案,在兩種編程方式上取得了微妙的平衡來發(fā)揮兩者的優(yōu)勢。 4、actor:actor模型是一種適用性很廣的并發(fā)編程模型,適用于共享內(nèi)存模型和分布式內(nèi)存模型, 也適合解決地理分布型問題,能提供強大的容錯性。 5、通信順序進程(Communicating Sequential Processes,CSP):表面上看,CSP模型與actor模 型很相似,兩者都基于消息傳遞。不過CSP模型側(cè)重于傳遞信息的通道,而actor模型側(cè)重于通道 兩端的實體,使用CSP模型的代碼會帶有明顯不同的風(fēng)格。 6、數(shù)據(jù)級并行:每個筆記本電腦里都藏著一臺超級計算機——GPU。GPU利用了數(shù)據(jù)級并行, 不僅可以快速進行圖像處理,也可以用于更廣闊的領(lǐng)域。如果要進行有限元分析、流體力學(xué)計算 或其他的大量數(shù)字計算,GPU的性能將是不二選擇。 7、Lambda架構(gòu):大數(shù)據(jù)時代的到來離不開并行——現(xiàn)在我們只需要增加計算資源,就能具有 處理TB級數(shù)據(jù)的能力。Lambda架構(gòu)綜合了MapReduce和流式處理的特點,是一種可以處理多種大數(shù)據(jù)問題的架構(gòu)。
四、線程與鎖:
class Counter { private int count = 0; public synchronized void increment() { ++count; } public int getCount() { return count; } } 毋庸置疑,對于增加了同步功能的代碼,每次執(zhí)行都將得到正確結(jié)果,但代碼中仍隱藏了一個bug。 潛藏的bug是: 除了increment()之外,getCount()方法 也需要進行同步。 否則,當(dāng)一個線程對值的修改沒有及時更新到主內(nèi)存,從而導(dǎo)致 調(diào)用getCount()的線程可能獲得一個失效的值。 解釋: Java內(nèi)存模型定義了何時一個線程對內(nèi)存的修改對另一個線程可見。 基本原則是,如果讀 線程和寫線程不進行同步,就不能保證可見性。 然而兩個線程都需要進行同步。只在其中一個線程進行同步是不夠的, 競態(tài)條件: 計算的正確性取決于多個線程的交替執(zhí)行時序時,就會發(fā)生競態(tài)條件。 1、亂序執(zhí)行。執(zhí)行依賴于檢測的結(jié)果,而檢測結(jié)果依賴于多個線程的執(zhí)行時序。 亂序原因: ? 編譯器的靜態(tài)優(yōu)化可以打亂代碼的執(zhí)行順序; ? JVM的動態(tài)優(yōu)化也會打亂代碼的執(zhí)行順序; ? 硬件可以通過亂序執(zhí)行來優(yōu)化其性能。
所以在多線程環(huán)境下,對一個文件的操作需要加鎖。
2、延遲初始化: 線程A和線程B同時執(zhí)行g(shù)etInstance,可能會取到兩個實例對象,主要看線程執(zhí)行時序了。 public class ObjFactory { private Obj instance; public Obj getInstance(){ if(instance == null){ instance = new Obj(); } return instance; } }
五、來自外星方法的危害
規(guī)模較大的程序常用監(jiān)聽器模式(listener)來解耦模塊。 在這里,我們構(gòu)造一個類從一個URL 進行下載,并用ProgressListeners監(jiān)聽下載的進度。 public class Downloader extends Thread { private InputStream in; private OutputStream out; private ArrayListlisteners; public Downloader(URL url,String outputFilename) throws IOException { in=url.openConnection().getInputStream(); out = new FileOutputStream(outputFilename); listeners=new ArrayList (); } public synchronized void addListener(ProgressListener listener){ listeners.add(listener); } public synchronized boolean remove(ProgressListener listener){ return listeners.remove(listener); } /*** * 來自外星方法的危害 * * addListener()、removeListener()和updateProgress()都是同步方法, * 多線程可以安全地使用這些方法。盡管這段代碼僅使用了一把鎖,但仍隱藏著一個死鎖陷阱。 * * 陷阱在于updateProgress()調(diào)用了一個外星方法——但對于這個外星方法一無所知。外星方法可以做任何事情, * 例如持有另外一把鎖。這樣一來,我們就在對加鎖順序一無所知的情況下使用了兩把鎖。就像前面提到的,這就有可能發(fā)生死鎖。 * * @param n */ private synchronized void updateProgress(int n){ for(ProgressListener listener:listeners){ listener.onProgress(n); } } /*** * 一種方法是在遍歷之前對listeners進行保 護性復(fù)制(defensive copy), * 再針對這份副本進行遍歷 * 這是個一石多鳥的方法。不僅在調(diào)用外星方法時不用加鎖,而且大大減少了代碼持有鎖的時間。 * 長時間地持有鎖將影響性能(降低了程序的并發(fā)度),也會增加死鎖的可能。 * @param n */ private void updateProgress2(int n){ ArrayList listenersCopy=null; synchronized (this){ listenersCopy=(ArrayList )listeners.clone(); } for(ProgressListener listener:listenersCopy){ listener.onProgress(n); } } @Override public void run(){ int n = 0, total = 0; byte[] buffer = new byte[1024]; try { while((n = in.read(buffer)) != -1) { out.write(buffer, 0, n); total += n; updateProgress(total); } out.flush(); } catch (IOException e) { e.printStackTrace(); } } }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/68656.html
摘要:使用進行并發(fā)編程篇三掘金這是使用進行并發(fā)編程系列的最后一篇。所以我考慮啟用一個本地使用進行并發(fā)編程篇二掘金我們今天繼續(xù)深入學(xué)習(xí)。 使用 Python 進行并發(fā)編程 - asyncio 篇 (三) - 掘金 這是「使用Python進行并發(fā)編程」系列的最后一篇。我特意地把它安排在了16年最后一天。 重新實驗上篇的效率對比的實現(xiàn) 在第一篇我們曾經(jīng)對比并發(fā)執(zhí)行的效率,但是請求的是httpb...
摘要:并發(fā)表示在一段時間內(nèi)有多個動作存在。并發(fā)帶來的問題在享受并發(fā)編程帶來的高性能高吞吐量的同時,也會因為并發(fā)編程帶來一些意想不到弊端。并發(fā)過程中多線程之間的切換調(diào)度,上下文的保存恢復(fù)等都會帶來額外的線程切換開銷。 0x01 什么是并發(fā) 要理解并發(fā)首選我們來區(qū)分下并發(fā)和并行的概念。 并發(fā):表示在一段時間內(nèi)有多個動作存在。 并行:表示在同一時間點有多個動作同時存在。 例如:此刻我正在寫博客,但...
摘要:在這個范圍廣大的并發(fā)技術(shù)領(lǐng)域當(dāng)中多線程編程可以說是基礎(chǔ)和核心,大多數(shù)抽象并發(fā)問題的構(gòu)思與解決都是基于多線程模型來進行的。一般來說,多線程程序會面臨三類問題正確性問題效率問題死鎖問題。 多線程編程或者說范圍更大的并發(fā)編程是一種非常復(fù)雜且容易出錯的編程方式,但是我們?yōu)槭裁催€要冒著風(fēng)險艱辛地學(xué)習(xí)各種多線程編程技術(shù)、解決各種并發(fā)問題呢? 因為并發(fā)是整個分布式集群的基礎(chǔ),通過分布式集群不僅可以大...
摘要:因為多線程競爭鎖時會引起上下文切換。減少線程的使用。舉個例子如果說服務(wù)器的帶寬只有,某個資源的下載速度是,系統(tǒng)啟動個線程下載該資源并不會導(dǎo)致下載速度編程,所以在并發(fā)編程時,需要考慮這些資源的限制。 最近私下做一項目,一bug幾日未解決,總惶恐。一日頓悟,bug不可怕,怕的是項目不存在bug,與其懼怕,何不與其剛正面。 系列文章傳送門: Java多線程學(xué)習(xí)(一)Java多線程入門 Jav...
摘要:關(guān)于并發(fā)編程,其目的就是為了讓程序運行得更快,但是,并不是啟動更多的線程就能讓程序更大限度的并發(fā)執(zhí)行。對于軟件資源限制考慮使用資源池將資源復(fù)用,例如數(shù)據(jù)庫連接池等資源限制情況下進行并發(fā)編程根據(jù)不同的資源限制調(diào)整程序的并發(fā)度。 關(guān)于并發(fā)編程,其目的就是為了讓程序運行得更快,但是,并不是啟動更多的線程就能讓程序更大限度的并發(fā)執(zhí)行。有哪些影響并發(fā)編程的因素呢? 一、文章導(dǎo)圖 showImg(...
摘要:相比與其他操作系統(tǒng)包括其他類系統(tǒng)有很多的優(yōu)點,其中有一項就是,其上下文切換和模式切換的時間消耗非常少。因為多線程競爭鎖時會引起上下文切換。減少線程的使用。很多編程語言中都有協(xié)程。所以如何避免死鎖的產(chǎn)生,在我們使用并發(fā)編程時至關(guān)重要。 系列文章傳送門: Java多線程學(xué)習(xí)(一)Java多線程入門 Java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(1) java多線程學(xué)習(xí)(二)syn...
閱讀 1294·2021-10-08 10:05
閱讀 4107·2021-09-22 15:54
閱讀 3105·2021-08-27 16:18
閱讀 3107·2019-08-30 15:55
閱讀 1436·2019-08-29 12:54
閱讀 2748·2019-08-26 11:42
閱讀 543·2019-08-26 11:39
閱讀 2129·2019-08-26 10:11