多執行緒-Java原子變數-java.util.concurrent.atomic.*
一個沒有併發控制的計數器:
- publicclass Counter implements Runnable {
- privatestaticint count;
- publicvoid run() {
- System.out.println(Thread.currentThread().getName()
- + ":" + (++count));
- }
- publicstaticvoid main(String[] args){
-
Counter counter = new Counter();
- Thread t1 = new Thread(counter);
- Thread t2 = new Thread(counter);
- Thread t3 = new Thread(counter);
- Thread t4 = new Thread(counter);
- t1.start();
- t2.start();
- t3.start();
- t4.start();
- }
- }
有時執行正常,但是偶爾會出現如下執行結果:
-
Thread-1:2
- Thread-0:1
- Thread-2:3
- Thread-3:3
這顯然和預期結果不太一樣,先用javap -verbose命令分析一下這個類,在位元組碼層面上,++count等價於虛擬機器順次執行如下5條位元組碼指令(不考慮執行期的優化)
- getstatic 獲取指定類的靜態域,並將其值壓入棧頂
- iconst_1 將int型1推送至棧頂
- iadd 將棧頂兩int型數值相加並將結果壓入棧頂
- dup 複製棧頂數值並將複製值壓入棧頂
- putstatic 為指定類的靜態域賦值
當Thread-3執行緒執行getstatic指令時,Thread-2執行緒還未執行至iadd指令,故Thread-3執行緒獲取的初始靜態域count的值和Thread-2執行緒一樣,都為2
本質原因就是++count雖然只是一行程式碼,但這一過程並非原子操作
要保證這種型別的原子操作,可以使用java.util.concurrent.atomic包下的類
- 軟體包 java.util.concurrent.atomic
- 類的小工具包,支援在單個變數上解除鎖的執行緒安全程式設計。
示例如下:
- publicclass Counter implements Runnable {
- privatefinal AtomicInteger count = new AtomicInteger(0);
- publicvoid run() {
- System.out.println(Thread.currentThread().getName()
- + ":" + count.incrementAndGet());
- }
- publicstaticvoid main(String[] args){
- Counter counter = new Counter();
- Thread t1 = new Thread(counter);
- Thread t2 = new Thread(counter);
- Thread t3 = new Thread(counter);
- Thread t4 = new Thread(counter);
- t1.start();
- t2.start();
- t3.start();
- t4.start();
- }
- }
看看原始碼中究竟是如何實現的
- privatevolatileint value;
- public AtomicInteger(int initialValue) {
- value = initialValue;
- }
- publicfinalint incrementAndGet() {
- for (;;) {
- int current = get();
- int next = current + 1;
- if (compareAndSet(current, next))
- return next;
- }
- }
- /**
- * Atomically sets the value to the given updated value
- * if the current value {@code ==} the expected value.
- *
- * @param expect the expected value
- * @param update the new value
- * @return true if successful. False return indicates that
- * the actual value was not equal to the expected value.
- */
- publicfinalboolean compareAndSet(int expect, int update) {
- return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
- }
- publicfinalint get() {
- return value;
- }
是不是和樂觀鎖很像,如果結果符合預期結果,就將結果返回,否則不斷進行重試,並沒有進行同步,兼顧了安全性和效能
java.util.concurrent.atomic包下還有很多類,使用這些類可以保證對這些類的諸如“獲取-更新”操作是原子性的,從而避發生競態條件
- AtomicBoolean 可以用原子方式更新的 boolean 值。
- AtomicInteger 可以用原子方式更新的 int 值。
- AtomicIntegerArray 可以用原子方式更新其元素的 int 陣列。
- AtomicIntegerFieldUpdater<T> 基於反射的實用工具,可以對指定類的指定 volatile int 欄位進行原子更新。
- AtomicLong 可以用原子方式更新的 long 值。
- AtomicLongArray 可以用原子方式更新其元素的 long 陣列。
- AtomicLongFieldUpdater<T> 基於反射的實用工具,可以對指定類的指定 volatile long 欄位進行原子更新。
- AtomicMarkableReference<V> AtomicMarkableReference 維護帶有標記位的物件引用,可以原子方式對其進行更新。
- AtomicReference<V> 可以用原子方式更新的物件引用。
- AtomicReferenceArray<E> 可以用原子方式更新其元素的物件引用陣列。
- AtomicReferenceFieldUpdater<T,V> 基於反射的實用工具,可以對指定類的指定 volatile 欄位進行原子更新。
- AtomicStampedReference<V> AtomicStampedReference 維護帶有整數“標誌”的物件引用,可以用原子方式對其進行更新。
相關推薦
多執行緒之原子變數CAS演算法(二)
上篇博文,我們介紹了多執行緒之記憶體可見性Volatile(一),但是也遺留了一個問題,如何保證變數的”原子性操作(Atomic operations)”? Volatile保證部分型別的原子性 上篇博文,我們說Voloatile不能保證原子性,有一點侷
多執行緒-Java原子變數-java.util.concurrent.atomic.*
一個沒有併發控制的計數器: publicclass Counter implements Runnable { privatestaticint count; publicvoid run() { System.out.
多執行緒學習筆記十三——java中的原子操作類
當程式更新一個變數時,如果多執行緒同時更新這個變數,可能得到期望之外的值,比如變 量i=1,A執行緒更新i+1,B執行緒也更新i+1,經過兩個執行緒操作之後可能i不等於3,而是等於2。因 為A和B執行緒在更新變數i的時候拿到的i都是1,這就是執行緒不安全
java多執行緒之共享變數
目的:簡述java多執行緒的共享變數 共享變數:多個執行緒都會使用到的同一變數。 Q : 為什麼共享變數會造成資料的錯誤呢??? A : 多個執行緒在操作共享變數的時候,不是直接在主記憶體中去操作的。而
java多執行緒的共享變數訪問控制例項
最近打算去一家電商公司,對於高併發的資料訪問控制有著嚴格的要求,近期打算把多執行緒的知識在好好補一下。 執行緒排程有五個狀態; 開始,可執行,執行,阻塞,死亡。 啟動執行緒有兩種方法。繼承Thread類或則實現Runnable介面,其實Thread類也實現
Java多執行緒中static變數的使用 SimpleDateFormat時間格式化存線上程安全問題
兩篇文章 Java多執行緒中static變數的使用 (轉自:http://blog.csdn.net/yy304935305/article/details/52456771) && SimpleDateFormat時間格式化存線上程安全問題
Java多執行緒之volatile變數
Java 語言中的 volatile 變數可以被看作是一種 “程度較輕的 synchronized”;與 synchronized 塊相比,volatile 變數所需的編碼較少,並且執行時開銷也較少,但是它所能實現的功能也僅是 synchronized 的一部分。本文介紹了幾種有效使用 volati
【Java多執行緒】共享變數&同步-非同步容器&執行緒區域性變數
共享變數 (Volatile Atomic) volatile:當多個執行緒訪問一個成員變數的時候,需要這個變數在多個執行緒中可見。 Atomic:Atomic方法對該變數的操作是原子性操作,顆粒度是到對這個變數的一次操作。 private stati
Java多執行緒之原子操作atomic的使用CAS(七)
3-5、java.util.concurrent.atomic:執行緒安全的原子操作包 在JDK1.5+的版本中,Doug Lea和他的團隊還為我們提供了一套用於保證執行緒安全的原子操作。我們都知道在多執行緒環境下,對於更新物件中的某個屬性、更新基本型別資料、更新陣列(
Java多執行緒操作區域性變數與全域性變數
在這篇文章裡,我們首先闡述什麼是同步,不同步有什麼問題,然後討論可以採取哪些措施控制同步,接下來我們會仿照回顧網路通訊時那樣,構建一個伺服器端的“執行緒池”,JDK為我們提供了一個很大的concurrent工具包,最後我們會對裡面的內容進行探索。 為什麼要執
Java多執行緒與高併發:java.util.concurrent包
面試官:你用過JUC的哪些工具類? 前面從基礎開始,到執行緒安全的實現、物件的釋出與共享,涉及到很多執行緒安全的類與工具,JDK1
Java多執行緒之原子操作類
在併發程式設計中很容易出現併發安全問題,最簡單的例子就是多執行緒更新變數i=1,多個執行緒執行i++操作,就有可能獲取不到正確的值,而這個問題,最常用的方法是通過Synchronized進行控制來達到執行緒安全的目的。但是由於synchronized是採用的是悲觀鎖策略,並不是特別高效的一種解決方案。實際上,
Java多執行緒——物件及變數的併發訪問
Java多線系列文章是Java多執行緒的詳解介紹,對多執行緒還不熟悉的同學可以先去看一下我的這篇部落格Java基礎系列3:多執行緒超詳細總結,這篇部落格從巨集觀層面介紹了多執行緒的整體概況,接下來的幾篇文章是對多執行緒的深入剖析。 本篇文章主要介紹Java多執行緒中的同步,也就是如何在Java語
java架構之路(多執行緒)原子操作,Atomic與Unsafe魔術類
這次不講原理了,主要是一些應用方面的知識,和上幾次的JUC併發程式設計的知識點更容易理解. 知識回顧: 上次主要說了Semaphore訊號量的使用,就是一個票據的使用,我們舉例了看3D電影拿3D眼鏡的例子,還說了內部的搶3D眼鏡,和後續排隊的原始碼解析,還有CountDownLatch的使用,我們是用
LINUX 多執行緒 JNI 回撥 java static
1.Linux 開啟執行緒 //渲染執行緒Rendering void* thread_rendering_process(void *lParam) { unsigned int local_wr; int index; &
java多執行緒系列翻譯之java併發/多執行緒教程
原文地址:http://tutorials.jenkov.com/java-concurrency/index.html 以前計算機都是單核,同時只能執行一個程式。之後出現了多重任務處理,這意味著計算機同時可以處理多個程式(又名任務或流程)。但這不是真正的“同時執行”,只是單個CPU被多個程式共
Java多執行緒(四)java中的Sleep方法
點我跳過黑哥的卑鄙廣告行為,進入正文。 Java多執行緒系列更新中~ 正式篇: Java多執行緒(一) 什麼是執行緒 Java多執行緒(二)關於多執行緒的CPU密集型和IO密集型這件事 Java多執行緒(三)如何建立執行緒 Java多執行緒(四)java中的Sleep方法
多執行緒(二)Java多執行緒,啟動四個執行緒,兩個執行加一,另外兩個執行減一
public class Test { public static void main(String[] args) { final ShareData data = new ShareData(); for (int i = 0; i < 2; i++) {
深入理解多執行緒(五)—— Java虛擬機器的鎖優化技術
本文是《深入理解多執行緒》的第五篇文章,前面幾篇文章中我們從synchronized的實現原理開始,一直介紹到了Monitor的實現原理。 前情提要 通過前面幾篇文章,我們已經知道: 1、同步方法通過ACC_SYNCHRONIZED關鍵字隱式的對方法進行加鎖。當執行緒要
java多執行緒:3、Java對多執行緒的支援1
宣告:本教程不收取任何費用,歡迎轉載,尊重作者勞動成果,不得用於商業用途,侵權必究!!! 文章目錄 1、Java在語言級提供了對多執行緒程式設計的支援。 2、實現多執行緒程式的兩種方式 3、後臺執行緒 4、yield方法 5、執行緒優先順序 1、Java在語言級提