java並發:原子類之AtomicLong


原子類之AtomicLong

java線程中的操作,需要滿足原子性、可見性等原則,比如i++這樣的操作不具備原子性,
A線程讀取了i,另一個線程執行i++,A線程再執行i++就會引發線程安全問題

推薦學習的AtomicInteger和AtomicLong博客

你還在用Synchronized?Atomic你了解不?
Java多線程系列--“JUC原子類”02之 AtomicLong原子類

一個非原子性的自加引發的安全例子

下面的例子執行1000個線程,有意思的還Long自加比Interger更容易發現結果是比1000小。

package com.java.javabase.thread.base.concurrent.atomic;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@Slf4j
public class AtomicLongtest   {

    public static void main(String[] args) {
        AtomicLongtest test =new AtomicLongtest();
        Count  count =test.new Count();
        ExecutorService service = Executors.newCachedThreadPool();
        for(int i=0;i<1000;i++){
            service.execute(()->count.increace());
        }
        service.shutdown();
        try {
            service.awaitTermination(1, TimeUnit.DAYS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("End count :{}",count.getCount());

    }
    @Data
    class Count{
        private Long count=0L;
        public void increace(){
            log.info("count {}",count++);
        }

    }
}

通過syncronized方法

通過syncronized方法使得自加操作安全

使用AtomicLong滿足原子性

使用AtomicLong滿足原子性主要是實現了CAS

比較並交換(compare and swap, CAS),是原子操作的一種,可用於在多線程編程中實現不被打斷的數據交換操作,從而避免多線程同時改寫某一數據時由於執行順序不確定性以及中斷的不可預知性產生的數據不一致問題。 該操作通過將內存中的值與指定數據進行比較,當數值一樣時將內存中的數據替換為新的值。

使用使用AtomicLong,1000個線程執行之后返回的結果是1000,保證了結果的正確

package com.java.javabase.thread.base.concurrent.atomic;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

@Slf4j
public class AtomicLongTest2 {
    public static void main(String[] args) {
        AtomicLongTest2 test =new AtomicLongTest2();
        Count count =test.new Count();
        ExecutorService service = Executors.newCachedThreadPool();
        for(int i=0;i<1000;i++){
            service.execute(()->count.increace());
        }
        service.shutdown();
        try {
            service.awaitTermination(1, TimeUnit.DAYS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("End count :{}",count.getCount());

    }
    @Data
    class Count{
        private AtomicLong count=new AtomicLong(0);
        public void increace(){
            log.info("count {}",count.incrementAndGet());
        }
    }
}

AtomicLong的ABA問題

CAS有一個問題是ABA問題:
1.ABC三個線程
2.count=10,這時AB線程的內存值和預期值都是10
3.B線程把count修改100成功后,內存值是100
4.A線程又把count設置為10
5.這個時候內存值和預期值都是10
6.c線程是不知道A和B對count做了什么操作的


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM