자바 에서 자주 사용 하 는 원자 류 를 상세 하 게 정리 하 다.
자바 에 서 는 원자 류 를 제공 하고 원자 류 는 변 수 를 포장 하 며 변 수 를 원자 적 으로 조작 하 는 일련의 방법 을 제공 했다.우 리 는 다 중 스 레 드 환경 에서 이런 원자 류 를 조작 할 때 자 물 쇠 를 추가 하지 않 아 도 되 고 병발 프로 그래 밍 의 개발 을 크게 간소화 했다.
2.원자 류 의 밑바닥 실현
현재 자바 에서 제공 하 는 원자 류 의 대부분 밑바닥 은 CAS 자물쇠(CompareAndSet 자선 자물쇠)를 사용 하고 있다.예 를 들 어 AtomicInteger,AtomicLong 등 이다.세그먼트 잠 금+CAS 잠 금 을 사용 한 원자 류,예 를 들 어 LongAdder 등 도 있다.
3.자주 사용 하 는 원자 류
3.1 AtomicInteger 와 AtomicLong
AtomicInteger 와 AtomicLong 의 밑바닥 실현 은 용법 과 기본적으로 같다.다른 점 은 AtomicInteger 가 Integer 형 변 수 를 포 장 했 고 AtomicLong 은 Long 형 변 수 를 포 장 했 기 때문이다.
AtomicInteger 와 AtomicLong 의 밑바닥 실현 은 모두 CAS 자 물 쇠 를 사용 했다.
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
/**
 * @author IT00ZYQ
 * @date 2021/5/24 15:33
 **/
public class T13_AtomicInteger {
    private static AtomicInteger atomicInteger = new AtomicInteger();
    private static AtomicLong atomicLong = new AtomicLong();
    private static Integer integer = 0;
    private static Long lon = 0L;
    public static void main(String[] args) {
        //   10   ,   atomicInteger、atomicLong、integer、lon  1000   1   
        //          ,       = 10 * 1000 = 10000
        Thread[] threads = new Thread[10];
        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 1; j <= 1000; j++) {
                    atomicInteger.incrementAndGet();
                    atomicLong.incrementAndGet();
                    integer ++;
                    lon ++;
                }
            });
        }
        //     
        for (Thread thread : threads) {
            thread.start();
        }
        //   10       
        try {
            for (Thread thread : threads) {
                thread.join();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("AtomicInteger   :" + atomicInteger);
        System.out.println("AtomicLong   :" + atomicLong);
        System.out.println("Integer   :" + integer);
        System.out.println("Long   :" + lon);
    }
}
AtomicInteger 결과:10000
AtomicLong 결과:10000
Integer 결과:4880
Long 결과:4350
Process finished with exit code 0
여러 차례 실 행 된 원자 류 AtomicInteger 와 AtomicLong 은 매번 정확 한 결 과 를 얻 을 수 있 지만 비 원자 류 Integer 와 Long 은 일반적으로 10000 에 이 르 지 못 하고 매번 결과 도 다 를 수 있 습 니 다.
3.2 LongAdder
LongAdder 의 밑바닥 은 분 단 자 물 쇠 를 사 용 했 고 각 단락 은 CAS 자 물 쇠 를 사 용 했 기 때문에 LongAdder 의 밑바닥 은 분 단 자물쇠+CAS 자 물 쇠 를 실현 했다.
위의 프로그램 에 LongAdder 변 수 를 추가 하여 테스트 합 니 다.
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
/**
 * @author IT00ZYQ
 * @date 2021/5/24 15:33
 **/
public class T13_AtomicInteger {
    private static AtomicInteger atomicInteger = new AtomicInteger();
    private static AtomicLong atomicLong = new AtomicLong();
    private static LongAdder longAdder = new LongAdder();
    private static Integer integer = 0;
    private static Long lon = 0L;
    public static void main(String[] args) {
        //   10   ,   atomicInteger、atomicLong、integer、lon  1000   1   
        //          ,       = 10 * 1000 = 10000
        Thread[] threads = new Thread[10];
        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 1; j <= 1000; j++) {
                    atomicInteger.incrementAndGet();
                    atomicLong.incrementAndGet();
                    integer ++;
                    lon ++;
                    longAdder.increment();
                }
            });
        }
        //     
        for (Thread thread : threads) {
            thread.start();
        }
        //   10       
        try {
            for (Thread thread : threads) {
                thread.join();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("AtomicInteger   :" + atomicInteger);
        System.out.println("AtomicLong   :" + atomicLong);
        System.out.println("Integer   :" + integer);
        System.out.println("Long   :" + lon);
        System.out.println("LongAdder   :" + longAdder);
    }
}
AtomicInteger 결과:10000
AtomicLong 결과:10000
Integer 결과:6871
Long 결과:6518
LongAdder 결과:10000
Process finished with exit code 0
LongAdder 류 도 결 과 를 정확하게 출력 할 수 있다.
4.원자 류 의 성능 테스트
4.1 테스트 프로그램
package juc;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
/**
 * @author IT00ZYQ
 * @date 2021/5/24 15:51
 **/
public class T14_AtomicClassPerformance {
    private static AtomicLong atomicLong = new AtomicLong();
    private static LongAdder longAdder = new LongAdder();
    /**
     *    
     */
    private static final int THREAD_COUNT = 100;
    /**
     *           
     */
    private static final int OPERATION_COUNT = 10000;
    public static void main(String[] args) {
        Thread[] threads = new Thread[THREAD_COUNT];
        
        //    AtomicLong       
        for (int i = 0; i < THREAD_COUNT; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < OPERATION_COUNT; j++) {
                    atomicLong.incrementAndGet();
                }
            });
        }
        long start1 = System.currentTimeMillis();
        //     
        for (Thread thread : threads) {
            thread.start();
        }
        //         
        try {
            for (Thread thread : threads) {
                thread.join();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long end1 = System.currentTimeMillis();
        //    LongAdder       
        for (int i = 0; i < THREAD_COUNT; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < OPERATION_COUNT; j++) {
                    longAdder.increment();
                }
            });
        }
        long start2 = System.currentTimeMillis();
        //     
        for (Thread thread : threads) {
            thread.start();
        }
        //         
        try {
            for (Thread thread : threads) {
                thread.join();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long end2 = System.currentTimeMillis();
        System.out.println("AtomicLong    : " + (end1 - start1) + "ms,     :" + atomicLong);
        System.out.println("LongAdder    : " + (end2 - start2) + "ms,     :" + longAdder);
    }
}
4.567914 시의 운행 결과
AtomicLong 실행 시간:40ms,실행 결과:100000
LongAdder 운행 시간:57ms,운행 결과:100000
Process finished with exit code 0
4.567914 시의 운행 결과
AtomicLong 실행 시간:108 ms,실행 결과:1000000
LongAdder 운행 시간:85ms,운행 결과:1000000
Process finished with exit code 0
4.567914 시의 운행 결과
AtomicLong 운행 시간:6909 ms,운행 결과:100000000
LongAdder 운행 시간:468 ms,운행 결과:100000000
Process finished with exit code 0
4.567914 시의 운행 결과
AtomicLong 운행 시간:788 ms,운행 결과:10000000
LongAdder 운행 시간:162 ms,운행 결과 10000000
Process finished with exit code 0
4.3 결과 분석
4
THREAD_COUNT = 100, OPERATION_COUNT = 1000충분 한 시간 동안 AtomicInteger 의 성능 은 LongAdder 보다 약간 높 을 것 이다.4.567914.증가 함 에 따라 LongAdder 의 성능 이 더욱 높 고 4.567914.충분 할 때 LongAdder 의 성능 은 AtomicInteger 보다 훨씬 높다.4.4 밑바닥 실현 분석
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.