久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

Java線程安全的三大核心是什么

145次閱讀
沒有評論

共計 1957 個字符,預計需要花費 5 分鐘才能閱讀完成。

本篇內容主要講解“Java 線程安全的三大核心是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓丸趣 TV 小編來帶大家學習“Java 線程安全的三大核心是什么”吧!

在開始之前我們先來看看什么是線程安全?

線程安全

線程安全可以簡單理解為一個方法或者一個實例可以在多線程環境中使用而不會出現問題。

在同一程序中運行多個線程本身不會導致問題,問題在于多個線程訪問了相同的資源。如,同一內存區(變量,數組,或對象)、系統(數據庫,web services 等)或文件。實際上,這些問題只有在一或多個線程向這些資源做了寫操作時才有可能發生,只要資源沒有發生變化, 多個線程讀取相同的資源就是安全的。

比如下面的代碼,在多線程環境中,可能就會出現線程不安全的問題:

想象下線程 A 和 B 同時執行同一個這段代碼,我們無法知道操作系統何時會在兩個線程之間切換。JVM 并不是將這段代碼視為單條指令來執行的。

++ 操作不是一個原子性的操作,同樣的 — 操作也不是原子性的操作。

原子性

原子性是指操作是不可分的。其表現在于對于共享變量的某些操作,應該是不可分的,必須連續完成。

比如上面的 ++ 操作,實際上 JMM 會分 3 步來完成。

1、讀取變量 xttblog 的值

2、xttblog 的值 +1

3、將值賦予變量 xttblog

這三個操作中任何一個操作過程中,xttblog 的值被人篡改,那么都會出現我們不希望出現的結果。所以我們必須保證這是原子性的。

所以想要實現 ++ 這樣的原子操作就需要用到 synchronized 或者是 lock 進行加鎖處理。

如果是基礎類的自增操作可以使用 AtomicInteger 這樣的原子類來實現 (其本質是利用了 CPU 級別的 的 CAS 指令來完成的)。

可見性

可見性是指一個線程對共享變量的修改,對于另一個線程來說是否是可以看到的。

為什么會出現這種問題呢?

我們知道,java 線程通信是通過共享內存的方式進行通信的,而我們又知道,為了加快執行的速度,線程一般是不會直接操作內存的,而是操作緩存。

java 線程內存模型:

實際上,線程操作的是自己的工作內存,而不會直接操作主內存。如果線程對變量的操作沒有刷新寫入到主內存的話,僅僅改變了自己的工作內存的變量的副本,那么對于其他線程來說是不可見的。而如果另一個變量沒有讀取主內存中最新的值,而是使用舊的值的話,同樣的也可以列為不可見。(可以理解數據庫中的幻讀,臟讀)

對于 jvm 來說,主內存是所有線程共享的 java 堆,而工作內存中的共享變量的副本是從主內存拷貝過去的,是線程私有的局部變量,位于 java 棧中。

那么我們怎么知道什么時候工作內存的變量會刷寫到主內存當中呢?

volatile 關鍵字就是用于保證內存可見性,當線程 A 更新了 volatile 修飾的變量時,它會立即刷新到主線程,并且將其余緩存中該變量的值清空,導致其余線程只能去主內存讀取最新值。

使用 volatile 關鍵詞修飾的變量每次讀取都會得到最新的數據,不管哪個線程對這個變量的修改都會立即刷新到主內存。

synchronized 和加鎖也能能保證可見性,實現原理就是在釋放鎖之前其余線程是訪問不到這個共享變量的。但是和 volatile 相比開銷較大。

另外 Java 中還存在 happens-before。在 JMM 中,如果一個操作執行的結果需要對另一個操作可見,那么這兩個操作之間必須存在 happens-before 關系。這個以后細說!

有序性

有序性是指程序在執行的時候,程序的代碼執行順序和語句的順序是一致的。

為什么會出現不一致的情況呢?

這是由于重排序的緣故。

在 Java 內存模型中,允許編譯器和處理器對指令進行重排序,但是重排在單線程中不會出現問題,但在多線程中可能會出現數據不一致的問題。

例如下面這段代碼:

正常情況下的執行順序應該是 1 2 3。但是有時 JVM 為了提高整體的效率會進行指令重排導致執行的順序可能是 2 1 3。但是 JVM 也不能是什么都進行重排,是在保證最終結果和代碼順序執行結果一致的情況下才可能進行重排。

重排在單線程中不會出現問題,但在多線程中會出現數據不一致的問題。

Java 中可以使用 volatile 來保證順序性,synchronized 和 lock 也可以來保證有序性,和保證原子性的方式一樣,通過同一段時間只能一個線程訪問來實現的。

除了通過 volatile 關鍵字顯式的保證順序之外,JVM 還通過 happen-before 原則來隱式的保證順序性。

其中有一條就是適用于 volatile 關鍵字的,針對于 volatile 關鍵字的寫操作肯定是在讀操作之前,也就是說讀取的值肯定是最新的。

到此,相信大家對“Java 線程安全的三大核心是什么”有了更深的了解,不妨來實際操作一番吧!這里是丸趣 TV 網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-08-04發表,共計1957字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 广东省| 叙永县| 祁门县| 洛宁县| 阜城县| 东乌珠穆沁旗| 建平县| 吉林省| 兴安盟| 门头沟区| 瓮安县| 宣汉县| 常宁市| 柘荣县| 涞水县| 临武县| 临沭县| 洛扎县| 怀远县| 民乐县| 进贤县| 江达县| 杭州市| 黄梅县| 类乌齐县| 潍坊市| 进贤县| 正阳县| 团风县| 黄石市| 慈溪市| 磐石市| 宁夏| 彭水| 榕江县| 忻城县| 襄汾县| 哈巴河县| 江北区| 南京市| 延庆县|