Java并發編程(多線程)中的相關概念

? ? 眾所周知,在Java的知識體系中,并發編程是非常重要的一環,也是面試中必問的題,一個好的Java程序員是必須對并發編程這塊有所了解的。

并發必須知道的概念

在深入學習并發編程之前,我們需要了解幾個基本的概念。

同步和異步

同步和異步用請求返回調用的方式來理解相對簡單。

同步:可以理解為發出一個請求后,必須等待返回結果才能執行后續的操作。

異步:請求發出后,不需要等待返回結果,可以繼續執行后續操作,異步請求更像是在另一個 “空間” 中處理請求的結果,這個過程不會影響請求方的其他操作。

舉個生活中的例子,比如我們去實體店買衣服,挑選完款式后下單讓售貨員去倉庫拿貨,在售貨員拿貨的過程你需要在店里等待,直到售貨員把衣服交給你后才算購物成功,這就相當于同步的過程。

不過,如果是在網上購物的話,我們只需下單并完成支付,對我們來說整個購物過程就算完成了。網上的商家接到訂單會幫我們加緊安排送貨,這段時間我們可以去做其他的事,比如去外面打個籃球之類的。等送貨上門并簽收商品就完事了,這個過程就相當于異步。

并發和并行

并發和并行的功能很相似,兩者都可以表示多個任務一起執行的情況,但本質上兩者其實是有區別的。

嚴格意義上來說,并行的多任務是真實的同時執行而并發更多的情況是任務之間交替執行,系統不停的在多個任務間切換執行,也就是 “串行” 執行

最直接的例子的就是我們的計算機系統,在單核CPU時代,系統表面上能同時進行多任務處理,比如聽歌的同時又瀏覽網頁,但真實環境中這些任務不可能是真實并行的,因為一個CPU一次只能執行一條指令,這種情況就是并發,系統看似能處理多任務是因為不停的切換任務,但因為時間非常短,所以在我們的感官來說就是同時進行的。而計算機系統真實的并行是隨著多核CPU的出現才有的。

臨界區

臨界區表示公共資源或是共享數據,可以被多個線程使用。但是每次只能有一個線程使用它,一旦臨界區的資源被占用,其他線程就必須等到資源釋放后才能繼續使用該資源。在Java程序開發中,對于這樣的資源一般都需要做同步的操作,例如下面的這段代碼,用的就是synchronized關鍵字來對臨界區資源進行同步

public class SyncTest implements Runnable {
//臨界區資源 public static SyncTest instance = new SyncTest(); @Override public void run() { synchronized (instance) { } } public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(new SyncTest()); Thread t2 = new Thread(new SyncTest()); t1.start(); t2.start(); t1.join(); t2.join(); } }

阻塞和非阻塞

阻塞和非阻塞通常用來形容多線程間的相互影響。比如一個線程占用了臨界區的資源,那么其他需要這個資源的線程就必須等待。等待的過程會使線程掛起,也就是阻塞。如果臨界區的資源一直不釋放的話,那么其他阻塞的線程就都不能工作了。

非阻塞則相反,強調的是線程之間并不互相妨礙,所有的線程都會不斷嘗試向前執行。

死鎖、饑餓和活鎖

這三種情況表示的是多線程間的活躍狀態,對于線程來說,以上的情況都是 “非友好” 的狀態。

1、死鎖一般是指兩個或者兩個以上的線程互相持有對方所需的資源,并且永遠在等待對方釋放的一種阻塞狀態。例如有兩個線程A和B同時共享臨界區的資源C,當A占用C時,B處于阻塞狀態,然而A的釋放需要用到B的資源,這樣一來,就變成了A一直在等待B,B也一直在等待A,互相之間永遠在等待對方釋放的狀態。

一般來說,死鎖的發生是由于程序的設計不合理導致,而且死鎖很難解決,最好的方式就是預防

2、饑餓是指某一個或者多個線程因為種種原因無法獲得所需的資源,導致一直無法執行。比如它的線程優先級太低,而高優先級的線程不斷搶占它所需的資源,導致低優先級資源無法工作。

3、活鎖的情況是線程一種非常有趣的情況,在生活中我們可能會碰到這樣的情況,那就是出門的時候可能會遇到有人要進門,你打算讓他先進門,他又打算讓你先出門,結果,兩個人都互相退后了,然后你打算先出門時對方也向前一步,來來回回就一直卡在門口。當然,這種事情正常人很快就能解決,但如果是線程碰到就沒那么幸運了。

如果兩個線程占用著公共的資源,并且秉承著 “謙讓” 的原則,主動把資源讓給他人使用,你讓我也讓,這樣就造成資源在兩個線程間不斷跳動但線程之間都拿不到資源的情況,這樣的情況就是活鎖了

線程安全

線程安全指的是多線程的安全。如果一段程序可以保證被多線程訪問后仍能保持正確性,那么程序就是線程安全的。一般來說,線程安全注重的是多線程開發中的共享數據的安全。就比如下面這段代碼:

public class ThreadSafety implements Runnable{
//共享數據 public static int i = 0; public void increase(){ for (int j= 0;j<10; j++){ i++; } }
@Override public void run() { increase(); } public static void main(String[] args) throws Exception{ ThreadSafety demo = new ThreadSafety(); Thread t1 = new Thread(demo); Thread t2 = new Thread(demo); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(i); } }

兩個線程 t1 和 t2 同時開啟,執行run方法,在我們的預想中,如果是線程安全的話,那么main的執行結果應該是20,但是因為 i 是共享數據,而程序沒有對 i 的操作做同步的處理,最終運行的結果并不是20,所以這種情況就不是線程安全的情況。

解決的辦法也比較簡單,可以利用synchronized關鍵字來修飾方法或代碼塊,這部分的知識也是并發編程中非常重要的一塊。

改進后的代碼如下:

public class ThreadSafety implements Runnable{
//共享數據 public static int i = 0; public void increase(){
synchronized(this){
 for(int j= 0;j<10; j++){ i++; }
}
 }
@Override public void run() { increase(); } public static void main(String[] args) throws Exception{ ThreadSafety demo = new ThreadSafety(); Thread t1 = new Thread(demo); Thread t2 = new Thread(demo); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(i); } }

?此時,兩個線程 t1 和 t2 同時開啟,執行run方法,資源i就是獨立的了,兩個線程會切換執行,當t1執行的時候,會通過synchronized同步鎖將i鎖住,等到t1執行完畢釋放鎖了之后,t2才會執行對i進行操作。

轉載于:https://www.cnblogs.com/zhaosq/p/10178265.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/449897.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/449897.shtml
英文地址,請注明出處:http://en.pswp.cn/news/449897.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

4、容器虛擬化網絡概述

Docker 網絡 Docker 的網絡實現其實就是利用了 Linux 上的網絡名稱空間和虛擬網絡設備&#xff08;特別是 veth pair&#xff09;。 Linux 網絡命名空間&#xff1a;https://www.jianshu.com/p/369e50201bce Linux虛擬網絡設備之veth&#xff1a; https://segmentfault.com/a/1…

Linux whoami命令、Linux su命令、Linux w命令

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 Linux whoami命令用于顯示自身用戶名稱。 顯示自身的用戶名稱&#xff0c;本指令相當于執行"id -un"指令。 語法 whoami […

Weekly 10

Algorithm 1.Remove Element What 移除數組中的指定元素,返回處理后的長度sum,并且數組前sum長度的元素為處理后的元素,不用額外數組&#xff0c;O(1)。How 用快慢指針,快指針遍歷,遇到不等于指定元素的替換掉慢指針,然后慢指針前進一位即可。Key Codesclass Solution {public …

大數據計算:如何僅用1.5KB內存為十億對象計數

摘要&#xff1a;AddThis的數據分析副總監Matt Abrams在High Scalability上發表了一篇文章&#xff0c;介紹了他們公司如何應對大數據。Matt Abrams表示&#xff0c;AddThis僅僅用了1.5KB內存的內存就計算了十億個不同的對象&#xff0c;這與他們所使用的計算方法分不開的。 A…

C#關鍵字的個人理解與注釋

C#關鍵字注釋&#xff1a;abstract&#xff1a;抽象as&#xff1a;類型轉換&#xff08;返回轉換結果&#xff09;base&#xff1a;基類bool&#xff1a;布爾類型break&#xff1a;條件中斷語句byte&#xff1a;字節case&#xff1a;條件語句catch&#xff1a;異常捕獲后執行ch…

Linux declare命令、Linux tail 命令

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 Linux declare命令用于聲明 shell 變量。 declare為shell指令&#xff0c;在第一種語法中可用來聲明變量并設置變量的屬性([rix]即為變…

詳解Nagios配置文件的邏輯關系

1.主配置文件/usr/local/nagios/etc/nagios.cfg a.定義了用戶和組 b.定義了某些具體參數 c.定義了配置文件和可以存放配置文件的文件夾 d.通過開頭的#號去注釋選項以達到關閉配置的效果 e.更改配置后&#xff0c;可以通過命令 /usr/local/nagios/bin/nagios –v /usr/local/na…

10 步讓你成為更優秀的程序員

這篇文章要介紹的&#xff0c;是我作為專業程序員這些年來學到的能真正提高我的代碼質量和整體工作效率的10件事情。 1. 永遠不要復制代碼 不惜任何代價避免重復的代碼。如果一個常用的代碼片段出現在了程序中的幾個不同地方&#xff0c;重構它&#xff0c;把它放到一個自己的函…

《流浪地球》 電影全集

《流浪地球》 電影全集 《流浪地球》是由郭帆導演&#xff0c;吳京特別出演&#xff0c;屈楚蕭、李光潔、吳孟達等人主演的科幻片《流浪地球》宣布定檔2019大年初一。同時&#xff0c;影片發布了一款定檔預告片&#xff0c;預告片開頭傳來一段廣播聲音&#xff1a;“太陽急速老…

kotlin之plus、copyOf、reverse、forEach、filter、map、reduce、fold等函數解釋和使用

kotlin之::函數調用、plus&#xff08;增加元素&#xff09;、copyOf&#xff08;復制數組&#xff09;、reverse&#xff08;翻轉數組&#xff09;、forEach&#xff08;遍歷數組&#xff09;、filter&#xff08;過濾數組&#xff09;、map函數操作及擴展、reduce函數、fold函…

linux 常用命令 雜記

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1.cat cat 命令用于連接文件并打印到標準輸出設備上。 使用權限 所有使用者 2.Linux chgrp命令用于變更文件或目錄的所屬群組。 3.Linux…

C程序員要學C++嗎?

最近網友問到這一問題&#xff0c;但我更希望被問的是“C程序員需要學面向對象編程嗎&#xff1f;”&#xff0c;那就讓我先從回答這一問題開始&#xff0c;并做適當的擴展。 就我的成長經歷來看&#xff0c;C程序員必須學習面向對象編程&#xff01;面向對象編程語言有其天然的…

追女生心理研究(本人母胎單身,就是想做準備,并無其他意思)

聊天話題&#xff1a; 1。興趣愛好&#xff1a;美食&#xff0c;旅游&#xff0c;寵物等 2。現在和曾經的自己&#xff0c;分享自己的經歷 3。我變成我們&#xff0c;未來規劃 4。分析隱私&#xff0c;比如一些小秘密 5。價值觀&#xff0c;對未來的規劃等 聊天話題技巧 …

dlopen 和 dlsym 動態調用函數

Linux/unix 提供了使用 dlopen 和 dlsym 方法動態加載庫和調用函數&#xff0c;這套方法在 macOS 和 iOS 上也支持。dlopen 打開一個庫&#xff0c;獲取句柄。dlsym 在打開的庫中查找符號的值。dlclose 關閉句柄。dlerror 返回一個描述最后一次調用dlopen、dlsym&#xff0c;或…

通過騰訊地圖服務獲取行政區劃信息

接口說明地址&#xff1a; https://lbs.qq.com/webservice_v1/guide-region.html 以下是源代碼及表創建腳本。 源碼及相關文件下載轉載于:https://www.cnblogs.com/challengesoflife/p/10405366.html

情感學習聊天方法

1.非正常聊天法 出人意料的聊天技巧&#xff0c;展示幽默感&#xff0c;讓對方對自己產生興趣 比如對方說&#xff1a;你的朋友圈好多美女啊。回答還好了&#xff0c;沒有了。場面會一度尷尬 但可以這么說&#xff1a;你這樣是在間接夸自己是美女。或者&#xff1a;還好啦&a…

面向對象設計的優點

一旦明白了軟件設計的真諦&#xff08;參見《軟件設計的真諦》&#xff09;&#xff0c;我們就更能理解面向對象設計的優點。簡單說來&#xff0c;它更便于我們在軟件中構建更真實的虛擬世界。 首先&#xff0c;對象的引入方便了在軟件虛擬世界中模擬現實世界。現實世界是由很…

利用SVD-推薦未嘗過的菜肴2

推薦未嘗過的菜肴-基于SVD的評分估計 實際上數據集要比我們上一篇展示的myMat要稀疏的多。 from numpy import linalg as la from numpy import * def loadExData2():return[[0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 5],[0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 3],[0, 0, 0, 0, 4, 0, 0, 1, 0,…

在圖像中截取小圖并保存

實現以橫向步長step_row、縱向步長step_col&#xff0c;在一幅大圖上剪裁寬度為width、高度為height的小圖像&#xff0c;圖像命名形式為“數字(遞增)_大圖名”格式&#xff0c;將小圖保存在argv[6]的文件夾中。 #include <opencv2/opencv.hpp> #include <string> …

Linux 文件與目錄管理、ls、cd、pwd、mkdir、rmdir、cp、 rm

見&#xff1a;http://www.runoob.com/linux/linux-file-content-manage.html我們知道Linux的目錄結構為樹狀結構&#xff0c;最頂級的目錄為根目錄 /。 其他目錄通過掛載可以將它們添加到樹中&#xff0c;通過解除掛載可以移除它們。 在開始本教程前我們需要先知道什么是絕對路…