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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

JAVA中关于并发的一些理解

發布時間:2025/4/5 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JAVA中关于并发的一些理解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

一,JAVA線程是如何實現的?

同步,涉及到多線程操作,那在JAVA中線程是如何實現的呢?

操作系統中講到,線程的實現(線程模型)主要有三種方式:

①使用內核線程實現

②使用用戶線程實現

③使用用戶線程加輕量級線程實現

?

二,JAVA語言定義了哪幾種線程狀態?

JAVA語言定義了五種線程狀態:①新建(New),當你 new 了一個Thread,但是并沒有調用它的 start()方法時,就處于這種狀態。

②運行(Run),這里包含了兩種狀態:一種是可運行狀態,就是你調用了Thread的start()方法之后,但是該線程還未獲得CPU(相當于操作系統中講的就緒狀態);另一種是運行狀態,就是該線程被調度器分配了CPU,正在執行。

③等待(Waiting),處于這種狀態的線程不會被分配CPU執行時間,它需要等待其他線程喚醒。等待又分成兩種:無限等待和超時等待(限期等待)。

無限等待一般是執行等待的方法沒有指定超時參數

比如Object類的wait()方法,會使線程進入無限等待狀態,它還有一個帶有 timeout(超時) 參數 的重載方法 Object.wait(long timeout),使線程超時等待。

調用Thread.sleep() 、 Object.wait()、Thread.join()方法都會使線程進入等待狀態。

④阻塞(Blocked),個人感覺阻塞是與鎖有關,而等待并不一定與鎖有關。

比如,兩個線程爭奪對象鎖(synchronized),未獲得鎖的那個線程將進入阻塞狀態。而線程進入等待狀態則有可能是因為③中提到的調用了Thread.sleep()方法,或者是線程讀某個Socket端口上的數據,但是此時數據還未到達,則線程進入等待狀態。

?⑤結束(Terminated),線程的run方法運行完畢,進入結束狀態。

?

三,同步(加鎖)為什么會有代價?

《深入理解JVM》中講到,在目前的JDK版本中,操作系統支持怎樣的線程模型,在很大程序上決定了JAVA虛擬機的線程是怎樣映射的。JAVA的線程是映射到操作系統的原生線程之上的,如果要阻塞或喚醒一個線程,都需要操作系統幫忙完成,這就需要從用戶態切換到核心態中,因此狀態轉換需要耗費很多的處理器時間

而在JAVA里面要實現同步,一種是使用對象鎖,即synchronized關鍵字;另一種則是使用 java.util.ReentrantLock。獲得鎖的線程進入臨界區執行、未獲得鎖的線程會阻塞,然后在某種條件下被喚醒。因此,同步(使用鎖)是有代價的。

?

四,對象鎖同步(synchronized同步) 與 ReentrantLock同步的區別

它們都是可重入鎖,可用來互斥同步,但主要有三個方面的區別

①使用synchronized進行同步的線程在阻塞等待時,是不可中斷的。而使用ReentrantLock進行同步的線程在阻塞等待時可中斷。

如果臨界區需要執行很長的時間,synchronized就只能一直阻塞等待了,而ReentrantLock 可以在阻塞等待一段時間之后,若還未獲得鎖,就可以被其他線程中斷,從而去干其他事情。一個很好的示例可參考:ReentrantLock鎖實現中斷線程阻塞

通過調用 lock.lockInterruptibly()方法來實現線程在阻塞等待時 可被其他線程 中斷。

?

②ReentrantLock可以實現公平鎖

?公平鎖是指多個線程在等待同一個鎖時,必須按照申請鎖的時間順序來依次獲得鎖。而非公平鎖則按照搶占的方式來獲得鎖,synchronized中的鎖是不公平的,而ReentrantLock可以在構造函數中指定創建的鎖是否為公平鎖。

public ReentrantLock(boolean fair) {sync = fair ? new FairSync() : new NonfairSync();}

?

③使用ReentrantLock 鎖可以同時綁定多個條件變量(Condition對象)

所謂 條件對象 就是說:線程好不容易獲得了鎖 進入臨界區,卻發現需要在滿足某一條件之后,它才能執行。因此,使用一個條件對象來管理那些已經獲得了鎖但是卻不能做有用工作的線程。

比如說:生產者--消費者模型,消費者獲得了隊列的鎖,去隊列中取產品,但是結果發現隊列為空,它沒有產品可消費。換句話說:它需要在隊列不為空的條件下,才能消費產品。(沒有產品,肯定無法消費產品啊!)

比如,消費者的代碼一般是下面這樣:進入consume()方法需要獲得鎖,但是卻發現隊列為空,故只能調用wait()方法 進入等待狀態。(不是阻塞狀態)

public synchronized void consume(){while(queue.isEmpty())wait();//沒有產品可消費,只能放棄鎖,并等待生產者線程生產了產品之后,喚醒它//consume productnotifyAll();//....}

?

那ReentrantLock呢?

Condition emptyCondition = lock.newCondition();Condition fullCondition = lock.newCondition();.......public synchronized void consume(){try{lock.lock();//ReentrantLock lockwhile(queue.isEmpty())emptyCondition.await();//consume productemptyCondition.singalAll();//....}finally{lock.unlock();}}

對于同一把ReentrantLock,它可以 new多個Condition,即同一把鎖可以關聯多個條件變量。

Condition.awit()方法的JDK源碼解釋非常值得一讀。部分摘錄如下:

Causes the current thread to wait until it is signalled or* {@linkplain Thread#interrupt interrupted}.* <p>The lock associated with this {@code Condition} is atomically* released and the current thread becomes disabled for thread scheduling* purposes and lies dormant until <em>one</em> of four things happens

調用Condition.await()方法使線程放棄鎖,并進入等待狀態(不是阻塞狀態),直到有下列四種情況發生 才從等待狀態退出.....

?.....

?

五,互斥同步 與 非阻塞同步 是什么?

所謂互斥同步,就是多個線程爭奪一把鎖時,未獲得鎖的那些線程將會阻塞。因此,互斥同步最主要的是進行線程阻塞和喚醒帶來的性能問題,因此 互斥同步稱為阻塞同步。從處理問題的方式上看,它是一種悲觀的并發策略:它認為如果不采取正確的同步措施,那執行就可能出問題。也就是說:它總是對共享數據先進行加鎖,然后再去訪問,盡管在訪問過程中 也許 并沒有 其他線程 訪問該共享數據。

而正如前面(三)中 提到,加鎖是有代價的,如果對共享數據加了鎖,但是在訪問共享數據過程中,并沒有其他線程來訪問該共享數據(即并沒有出現競爭),那這次加鎖就感覺有點浪費了。(就相當于:花了大量的人力、物力應對某次可能發生的地震,但是最終地震沒有發生)

于是,為了進一步的”優化“,就出現了基于沖突檢測的樂觀并發策略

樂觀并發策略就是:先進行操作,如果沒有其他線程爭用共享數據,那么操作就成功了。如果數據有爭用,產生了沖突,那再采用補救措施。

因此,樂觀并發策略的很多實現都不需要把線程掛起(因為它是 先執行了 操作再說),因而稱為:非阻塞同步。

樂觀并發策略需要硬件指令集的支持。因為,它在操作的過程中需要檢測是否發生了沖突,需要“操作”和“沖突檢測”這兩個步驟具備原子性。原子性如何保證?如果用互斥同步保證 那就又變回 悲觀并發策略 了,因此只能靠硬件來保證原子性。

比如java.util.concurrent.atomic.AtomicInteger.java 中的自增加1方法getAndIncrement(),就是通過硬件原子指令:CAS指令(Compare and swap)來實現

public final int getAndIncrement() {for (;;) {int current = get();int next = current + 1;if (compareAndSet(current, next))return current;}}public final boolean compareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}

?

六,關于鎖優化的一些知識

1)自旋鎖 的 實現思想

在多核CPU下,一個線程獲得鎖進入臨界區占用CPU執行時,我們有理由相信這個臨界區代碼很快就會執行完成,即: 共享數據的鎖定狀態只會持續很短的一段時間,而當另外一個線程剛好在這段時間去搶占鎖,掛起這個搶占鎖的線程有點 不值得。(畢竟占用鎖的線程很快就會把鎖釋放了呀)

于是,就讓請求搶占鎖的那個線程“稍微等待一下”,但不放棄處理器的執行時間(一旦放棄,就意味著需要掛起和恢復線程了),看持有鎖的線程是否很快就會釋放鎖。為了讓線程等待一下,我們只需讓線程執行一個忙循環(自旋),這就是:自旋鎖。

?

2)自旋鎖的“改進”---自適應自旋

?自旋等待避免了線程切換的開銷,但是它是要占用處理器時間的。因此,如果鎖被占用的時間很短,那自旋等待的效果就會非常好;如何鎖被占用的時間很長,執行忙循環(自旋)的線程就白白消耗處理器資源,造成性能上的浪費。默認情況下,自旋的次數是10次,但可以通過JVM參數進行修改。

為了應對鎖被占用很長時間 而導致的長時間無效的自旋,自旋的時間必須有一定的限度。

那如何確定一個合適的限定呢?這就是自適應自旋的目標了。

自適應自旋對自旋的次數沒有固定,比如說:在同一個鎖對象,自旋等待剛剛成功獲得過鎖,那么這次也很有可能成功,進而允許自旋等待持續相對更長的時間。

再比如說,對于某個鎖,自旋很少成功獲得過鎖,那在以后獲取這個鎖時可省略自旋過程,以避免處理器資源浪費。

?

3)輕量級鎖和偏向鎖

?個人感覺輕量級鎖和偏向鎖 的功能 與 緩存 的思想有點像。直接同步互斥加鎖的代價是很大的(重量級鎖),那我們可以先來一個輕量級鎖或偏向鎖。

如果在加了 輕量級鎖或偏向鎖的過程中?沒有發生其他線程來爭搶鎖(類似于緩存命中!)這意味著整個過程“幾乎”不需要同步。

如果有其他線程爭搶鎖,那輕量級鎖將不再有效(偏向鎖的偏向模式失效),輕量級鎖要膨脹為“重量級鎖”,后面等待鎖的線程要進入阻塞狀態。這就是類似于緩存未命中!

關于輕量級鎖和偏向鎖的具體解釋:可參考《深入理解JVM》

?

上面關于鎖的優化是JVM的一些鎖優化策略,在應用層進行鎖優化方式有如下:

①盡量減少鎖的持有時間。只對必要的需要同步的代碼進行同步。

synchronized{this} {methodA();// 把不需要同步的方法放到 sync 外面去mutex();//other method...// 把不需要同步的方法放到 sync 外面去 }

?

②減少鎖的粒度

ConcurrentHashMap就很好的應用了這種思想。它將整個HashMap分成了若干個段(Segment),每個段都有自己的鎖,每個段負責管理HashMap中的一部分HashEntry,段與段之間的HashEntry互不干擾,多線程可以并行地操作不同的Segment管理下的HashEntry。

這樣鎖的粒度就減少了。如果整個HashMap只有一把鎖管理,鎖的粒度就很大。操作HashMap不同的區域都需要互斥同步。而ConcurrentHashMap將HashMap分解成段,每個段有一把鎖,鎖的粒度就少了。但是與此同時,鎖的數量增多了。當需要訪問ConcurrentHashMap的全局屬性時(比如ConcurrentHashMap的size()方法),需要 獲得 所有的段的鎖。

1 try { 2 for (;;) { 3 if (retries++ == RETRIES_BEFORE_LOCK) { 4 for (int j = 0; j < segments.length; ++j) 5 ensureSegment(j).lock(); // force creation

以上是size()方法的部分代碼,size()的具體實現肯定也有相應的優化。

?

③鎖分離

鎖分離與鎖分段有點相似,鎖分離就是對不同的操作使用不同的鎖。比如,java.util.concurrent.LinkedBlockingQueue 是一個線程安全的阻塞隊列,take()方法從隊列中取元素,put()方法向隊列中添加元素。

這個隊列是用鏈式存儲結構實現,它的結點類如下:

1 /**2 * Linked list node class3 */4 static class Node<E> {5 E item;6 7 /**8 * One of:9 * - the real successor Node 10 * - this Node, meaning the successor is head.next 11 * - null, meaning there is no successor (this is the last node) 12 */ 13 Node<E> next; 14 15 Node(E x) { item = x; } 16 }

它的 put 操作 和 take 操作分別作用于隊列的尾部和頭部,并沒有相互沖突。如果 take 和 put 都共享同一把鎖,那么從隊列中取走元素的同時,就不能向隊列中添加元素,盡管它們互不“干擾”。

因此,為了提高并發效率,就使用了兩把鎖:一把 put 鎖,一把 take 鎖。這就是鎖分離機制。

1 /** Lock held by take, poll, etc */2 private final ReentrantLock takeLock = new ReentrantLock();3 4 /** Wait queue for waiting takes */5 private final Condition notEmpty = takeLock.newCondition();6 7 /** Lock held by put, offer, etc */8 private final ReentrantLock putLock = new ReentrantLock();9 10 /** Wait queue for waiting puts */ 11 private final Condition notFull = putLock.newCondition();

?

take鎖對應著 notEmtpy條件變量,putLock對應著一個 notFull條件變量。

在大部分情況下,多線程可以同時并行地向阻塞隊列中添加元素和取出元素。比如線程A向隊列添加元素的時候,并不阻塞線程B從隊列中取出元素。

通過使用 take 鎖 和 put 鎖,將LinkedBlockingQueue的讀寫分離。優化了并發效率。

?

④鎖粗化

這個與①中的盡量減少 鎖的時間 思想相反。但它們適用的情況是不同的。

比如,當程序需要在 for 循環內部加鎖時,每執行一次 for 循環中的操作就需要加鎖一次,加鎖之后執行臨界區代碼后又釋放鎖,這樣加鎖、釋放鎖的頻率非常大,效率反而低了。

1 public void syncMethod(){2 for(int i = 0; i < COUTN; i++)3 {4 synchronized(this){5 mutex();6 }7 //do something, do not need lock8 synchronized(this){9 mutex(); 10 } 11 //do another thing which needs no lock 12 } 13 }

?

這樣,直接用synchronized修飾方法反而要更好一點。

?

七,參考資料

《深入理解JVM》周志明

http://thrillerzw.iteye.com/blog/2055486

?

原文:http://www.cnblogs.com/hapjin/p/5765573.html

轉載于:https://my.oschina.net/u/3787897/blog/1630673

總結

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

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

主站蜘蛛池模板: 沟厕沟厕近拍高清视频 | 天天躁日日躁aaaaxxxx | 国产精品亚洲二区在线观看 | 深夜福利成人 | 天天综合日日夜夜 | av软件在线观看 | 在线观看亚洲精品视频 | 精品久久免费 | 日韩中出在线 | 337p粉嫩色噜噜噜大肥臀 | 91黑丝美女 | 日本一卡二卡在线 | 国产精品久久久久久久久久 | 精品日韩在线播放 | 内射后入在线观看一区 | 高清国产一区二区三区四区五区 | 国产精品天天干 | 老司机综合网 | www.avcao| 久久97精品 | 99国产精品无码 | 特大黑人巨交性xxxx | 国产在线看片 | 国产妇女视频 | 国产又粗又猛又爽又黄的视频在线观看动漫 | 欧美激情欧美激情在线五月 | 男女男网站 | 999精品在线视频 | 免费精品无码AV片在线观看黄 | 日韩欧美中文一区 | 欧美a级在线 | 第九色 | 国产视频999 | 麻豆av电影在线 | av国产一区二区 | 亚洲97视频 | 青青久久国产 | 性欧美丰满熟妇xxxx性仙踪林 | 黄色av电影网站 | 在线网站av | 在线视频 日韩 | 最近中文字幕 | 青青草成人免费在线视频 | 国产大学生自拍视频 | 亚洲成人免费在线视频 | 色婷婷av一区二区三区在线观看 | 麻豆md0034在线观看 | 五月天婷婷社区 | 欧美色图亚洲天堂 | www插插插无码免费视频网站 | 狠狠操夜夜操 | 97爱视频| 国产欧美在线看 | 四虎国产 | 欧美高清一区 | 亚洲一卡二卡 | 黄色片网站视频 | 福利姬在线观看 | 国产精品久久久久久久久久久久久 | 欧美大片在线播放 | 久久久久久久久久久久 | 欧美特级黄| 国产sm主人调教女m视频 | 狠狠干in | 一本色道久久综合狠狠躁 | 欧美激情电影一区二区 | 久久只有这里有精品 | 欧美夜夜操 | 欧美三级大片 | 另类综合在线 | 久久一区欧美 | 中文字幕乱码av | 日本老肥婆bbbwbbbwzr | a级片一级片 | 国产视频一二三区 | 久久久天天| 欧美一级特黄aa大片 | 密臀av在线 | 欧美精品一区二区三区久久久 | 波多野结衣理论片 | 熟女毛毛多熟妇人妻aⅴ在线毛片 | 精品妇女一区二区三区 | 91av网址 | 友田真希一区二区 | 99精品在线观看 | 精品成人久久 | 樱花草av| 久av在线 | 欧美一及片 | 精品久久一区 | 欧美在线导航 | 超碰超碰超碰超碰超碰 | 黄色福利在线观看 | 国产精品伦子伦免费视频 | 国产永久免费无遮挡 | 国产丝袜网站 | 激情三区 | 久久福利小视频 | 91精品成人 |