Java Syncrhonisers
線程通信主要通過共享對字段和對象的訪問來發(fā)生。 盡管這種通信方式非常高效,但它易于出現(xiàn)諸如線程干擾和內(nèi)存一致性之類的錯誤。 同步是一種有助于防止此類錯誤的工具。
但是,同步不是免費提供的,并且在訪問當前由另一個線程持有的鎖或?qū)ο髸r會引入延遲。 等待中的線程無法使用該對象,直到另一個線程釋放該對象上的鎖。 這種情況稱為線程爭用。 它還可能導致死鎖和活鎖。
在本文中,我們將探討Java提供的用于處理線程同步的不同選項。
同步要點
Java提供了一系列機制來處理基本線程同步和協(xié)調(diào)。 它支持通過同步方法和同步語句進行細粒度的對象訪問同步。 基本線程協(xié)調(diào)可以通過受保護的塊來完成。 所有提到的機制都是圍繞獲取和釋放對象的固有鎖定而構(gòu)建的。
內(nèi)在鎖
每個Java對象都有一個關(guān)聯(lián)的固有鎖。 需要對對象的字段進行獨占訪問的線程必須在訪問對象之前獲取對象的鎖,然后在完成后釋放固有的鎖。 其他嘗試訪問該對象的線程將阻塞,直到持有鎖的線程將其釋放為止。
同步方法
當線程調(diào)用同步方法時 ,它獲取該方法對象的內(nèi)在鎖 ,并在方法返回時釋放它。 即使該方法由于未捕獲的異常而返回,也將釋放該鎖定。 如果以靜態(tài)方法完成,則線程將獲取與該類關(guān)聯(lián)的類對象的鎖。
同步語句
提供更細粒度的同步機制。 同步語句必須指定提供內(nèi)部鎖的對象。 在分離的鎖對象上進行同步可以提供字段同步,而無需強制方法調(diào)用之間進行同步。
守衛(wèi)的塊
如前所述,受保護的塊為線程協(xié)調(diào)提供了支持。 受保護的塊是每個Java對象的一部分,可以使用wait , notify和notifyAll方法構(gòu)造。
wait方法掛起當前線程。 當線程調(diào)用wait時,它必須擁有對象的固有鎖,這就是為什么wait調(diào)用通常包裝在同步方法或語句中的原因。 調(diào)用wait方法將掛起線程執(zhí)行并釋放鎖。
在某個時刻,另一個線程將獲取對象的固有鎖,并調(diào)用notifyAll來通知所有線程等待發(fā)生重要事件。 在第二個線程釋放鎖之后,等待的線程將重新獲取該鎖,并通過從等待調(diào)用中返回來恢復執(zhí)行。
Notify喚醒單個線程。 無法指定喚醒的具體線程,因此,僅在我們不關(guān)心哪個線程被喚醒時才有用。
Java同步器
Java還提供了五個用于通用特殊用途同步的類。
CountDownLatch
CountDownLatch類允許一個或多個線程等待,直到其他線程中的一組操作完成。 用計數(shù)編號初始化。
await方法將阻塞,直到計數(shù)達到零為止。
countDown方法減少計數(shù)。
當await方法返回時,將釋放所有等待線程,并且隨后的await調(diào)用將立即返回。 計數(shù)無法重置。
信號
信號量用于限制線程對特定資源的訪問。 初始化具有許多許可證。
acquire方法將一直阻塞,直到獲得許可并獲得許可為止。
release方法添加許可,釋放阻止獲取者。
請注意,調(diào)用release不一定必須由稱為Acquisition的線程進行。 信號量可以是公平的,也可以是不公平的 。 如果公平,則線程以FIFO方式獲取許可。
盡管起初它看上去與CountDownLatch類似,但其目的卻完全不同。
循環(huán)屏障
CyclicBarrier建立在各方概念的周圍。 它允許線程等待彼此到達一個公共的障礙點。
await方法將阻塞,直到各方到達為止。 它的行為與CountDownLatch的逆過程相同。 N等待之后,它繼續(xù)。
它支持每個障礙點運行一次的可選可運行對象。 在最后一個聚會到達之后,但在釋放之前。 它通常用于更新線程之間的共享狀態(tài)。 它是循環(huán)的,因為它可以在線程釋放后重用 。
交換者
Exchanger是兩個線程可以交換信息的同步點。
線程將阻塞,直到其對方顯示其信息為止。 雙方都發(fā)生相同的行為。
移相器
Phaser是一個可重用的屏障,類似于CountDownLatch和CyclirBarrier ,但更加靈活。
在Phaser中,創(chuàng)建時注冊方的數(shù)量不是固定的。 雙方可以在通過任何注冊時register或bulkRegister方法。 雙方可以在抵達時注銷arriveAndDeregister 。
它提供了幾種同步方法。 arriveAndAwaitAdvance方法的行為與CycleBarrier await方法的行為相同。 arrive和arrive并arriveAndDeregister記錄到達,但不要阻塞。 awaitAdvance阻塞,直到各方到達為止。
它可以終止 ,強制所有同步方法返回。 可以通過forceTermination方法強制forceTermination 。
它還提供了監(jiān)視其狀態(tài)的支持。 值得注意的是,同步方法只能由注冊方調(diào)用,而狀態(tài)可以由任何調(diào)用者監(jiān)視。 監(jiān)視方法包括getRegisteredParties和getArrivedParties等。
結(jié)論
多線程絕對不是一個簡單的問題,但是使用某些語言提供的工具可以更輕松地解決多線程問題。 就個人而言,我不需要每天使用所有工具,但是我認為有必要知道它們的存在以及如何提供幫助。
翻譯自: https://www.javacodegeeks.com/2016/08/the-java-syncrhonisers.html
總結(jié)
以上是生活随笔為你收集整理的Java Syncrhonisers的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 苹果在美国扩充卫星 SOS 服务,购买
- 下一篇: 苹果 watchOS 10 RC 版发布