[Java并發(fā)編程實戰(zhàn)]簡介

并發(fā)簡史

在早期不包含操作系統(tǒng)的計算機中,程序都是單一的串行程序,從頭至尾只能執(zhí)行一個程序,并且這個程序訪問這個計算機的所有資源。然而,隨著技術(shù)的發(fā)展,操作系統(tǒng)出現(xiàn)了。它使得計算機程序有了進程,線程的概念,每次可以運行多個程序,并且不同的程序都在單獨的進程中運行。操作系統(tǒng)為各個獨立執(zhí)行的進程分配各種資源,包括內(nèi)存,文件句柄,安全證書等。不同進程之間通過系統(tǒng)本身的通信機制來交換數(shù)據(jù),如:套接字,信號處理器,共享內(nèi)存,信號量以及文件等。
操作系統(tǒng)支持多個程序同時執(zhí)行,原因主要有:

創(chuàng)新新互聯(lián),憑借十多年的網(wǎng)站建設(shè)、成都網(wǎng)站建設(shè)經(jīng)驗,本著真心·誠心服務(wù)的企業(yè)理念服務(wù)于成都中小企業(yè)設(shè)計網(wǎng)站有近千家案例。做網(wǎng)站建設(shè),選創(chuàng)新互聯(lián)。

  1. 資源利用率。如某個程序在等待一個耗時操作完成,那么在等待的同時可以運行另外一個程序,這樣可以提高資源利用率。

  2. 公平性。如通過時間片的方式讓程序輪流占用計算機資源,而不是由一個程序從頭至尾運行完,再進行下一個。

  3. 便利性。編寫多個程序來計算多個任務(wù),必要時進行通信。比只編寫一個程序來計算所有任務(wù)更加容易實現(xiàn)。

串行編程模型優(yōu)勢在于直觀性和簡單性,每次只做一件事直至完成,然后再做另外一件。然而很多情況下,這個串行模型并不理想。打個比方,我們想燒水泡茶然后看書,以串行的工作方式,我們必須等到水燒開了把茶泡好,才能去看書。而現(xiàn)實生活中,完全可以燒水的過程先去看書,然后等待水燒開在去泡茶。這也引出了計算機應(yīng)用程序用,同步和異步的概念。正是這些原因,促使進程,線程的出現(xiàn)。

線程,也被稱為輕量級進程?,F(xiàn)在大多數(shù)操作系統(tǒng)中,都是以線程為基本的調(diào)度單位,而不是進程。一個進程可以創(chuàng)建多個線程,并且這些線程會共享進程范圍內(nèi)的資源。所以,多個線程如果沒有明確的協(xié)同機制,那么他們是獨立運行的。同樣,這些線程都可以訪問進程的變量,如果沒有明確的同步機制來協(xié)同對共享數(shù)據(jù)的訪問,那么當(dāng)一個線程正在使用某個變量時,另外一個線程可能同時訪問這個變量,造成不可預(yù)測的結(jié)果。但是,每個線程都有各自的計數(shù)器,棧以及局部變量等。

線程的優(yōu)勢

如果使用得當(dāng),可以降低開發(fā),維護成本,提升性能。線程還可以降低代碼復(fù)雜度,使得代碼更容易編寫,閱讀和維護。在GUI 程序中,可以提高界面的響應(yīng)速度;在服務(wù)端程序中,可以提升資源利用率和吞吐率。

  • 發(fā)揮多核處理器的強大能力。

  • 建模的簡單性。將復(fù)雜且異步的工作流分解到各個線程運行,在特定的同步位置進行交互。

  • 異步事件的簡化處理。某個線程的阻塞不影響其他線程的處理。

  • 響應(yīng)更靈敏的用戶界面。使用特定線程來處理耗時操作,而不是放在UI主線程中處理。比如 Android App 耗時事件不能在 UI 線程處理,會影響 UI 響應(yīng)的流暢度。

線程的風(fēng)險

Java 對線程的使用是一把雙刃劍。線程的優(yōu)勢我們都已經(jīng)知道,前提是我們能夠正確的編寫出安全的并發(fā)代碼。然而,由于開發(fā)人員的技術(shù)不足,并發(fā)潛在風(fēng)險的不易察覺,都有可能讓我們的程序達不到預(yù)期的效果。所以,我們有必要了解一下并發(fā)風(fēng)險這一方面的內(nèi)容。

安全性問題

多個線程的執(zhí)行順序,在沒有同步的情況下是不可預(yù)測的,甚至產(chǎn)生奇怪的結(jié)果。如下面這個序列生成類,多個線程同時獲取到的值可能是相同的。

1    public class UnsafeSequene{
2        private int value;
3        //返回一個唯一的數(shù)值
4        public int getNext(){
5            return value++;
6        }
7    }

遞增操作 value++,實際上他包含三個獨立的操作:

  1. 讀取 value 的值

  2. 將 value 加 1

  3. 將計算結(jié)果寫入 value
    由于多個線程之間的操作交替執(zhí)行,所以可能發(fā)生兩個線程讀到相同的值。如下圖所示的 A 線程和 B 線程: 
    [Java并發(fā)編程實戰(zhàn)] 簡介這里寫圖片描述
    上圖說明的是一種常見的并發(fā)安全問題,稱為競態(tài)條件(Race Condition)。由于多個線程共享相同的內(nèi)存地址空間,并且是并發(fā)運行,因此可能會訪問或修改其他線程正在使用的變量。這種方式比其他線程間通信機制更容易實現(xiàn)數(shù)據(jù)共享,但他同樣也帶來了巨大的風(fēng)險:線程由于無法預(yù)料數(shù)據(jù)的變化而發(fā)生錯誤。

幸運的是,Java 提供了各種同步機制來協(xié)同這種訪問。上面的示例代碼,把它改成一個同步方法,就可以防止這種錯誤的發(fā)生。

1public class UnsafeSequene{
2    private int value;
3    //返回一個唯一的數(shù)值
4    public synchronized int getNext(){
5        return value++;
6    }
7}

活躍性問題

安全性的含義是,永遠不發(fā)生糟糕的事情。活躍性是,某件正確的事情最終會發(fā)生。當(dāng)某個操作無法繼續(xù)執(zhí)行下去時,就會發(fā)生活躍性問題,比如程序代碼進入死循環(huán)。所線程導(dǎo)致的死鎖,也是活躍性問題,比如線程 A 在等待線程 B 釋放其持有的資源,而線程 B 永遠都不釋放改資源,那么,線程 A 就會永遠的等待下去。

性能問題

活躍性意味著某件正確的事情最終會發(fā)生,但卻不夠好。這就是性能問題,因為我們通常希望正確的事盡快發(fā)生。性能問題包括:服務(wù)時間過長,響應(yīng)不靈敏,吞吐率過低,資源消耗過高等。

良好的并發(fā)程序,線程能提高性能,但無論如何,總會帶來某種程度的運行時開銷。
1.線程調(diào)度臨時掛起活躍線程并轉(zhuǎn)而運行另一個線程時,就會頻繁的出現(xiàn)上下文切換,帶來極大的開銷:保存和恢復(fù)執(zhí)行上下文,CPU 時間更多的花在線程調(diào)度而不是線程運行上。
2.使用同步機制,往往會抑制某些編譯器優(yōu)化。

線程無處不在

即使在程序中沒有顯示的創(chuàng)建線程,但在框架中仍可能會創(chuàng)建線程,因此在這些線程中調(diào)用的代碼同樣必須是線程安全的。框架通過在框架線程中調(diào)用應(yīng)用程序代碼將并發(fā)性引入到程序中。在代碼中將不可避免地訪問應(yīng)用程序狀態(tài),因此所有訪問這些狀態(tài)的代碼路徑都必須是線程安全的。

下面給出的模塊都將在應(yīng)用程序之外的線程中調(diào)用應(yīng)用程序的代碼。

  1. Timer

  2. Servlet 和 JavaServer Page

  3. 遠程調(diào)用方法

  4. Swing 和 AWT

本文原創(chuàng)首發(fā)于微信公眾號 [ 林里少年 ],歡迎關(guān)注第一時間獲取更新。

[Java并發(fā)編程實戰(zhàn)] 簡介這里寫圖片描述

網(wǎng)站名稱:[Java并發(fā)編程實戰(zhàn)]簡介
網(wǎng)頁URL:http://muchs.cn/article46/ihdshg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)網(wǎng)站制作、網(wǎng)站收錄、App開發(fā)、App設(shè)計搜索引擎優(yōu)化、ChatGPT

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司