자바 Atomic 클래스 및 스 레 드 동기 화 새로운 메커니즘 원리 분석
다음 애플 릿 을 보 세 요.아 날로 그 계수,10 개의 스 레 드 를 만 들 고 이 int count=0 에 공동으로 접근 합 니 다.모든 스 레 드 는 count 에 10000 을 추가 합 니 다.이 럴 때 자 물 쇠 를 추가 해 야 합 니 다.자 물 쇠 를 추가 하지 않 으 면 스 레 드 안전 문제 가 발생 할 수 있 습 니 다.그러나 Atomic Integer 를 사용 한 후에 자 물 쇠 를 추가 하 는 작업 을 하지 않 아 도 됩 니 다.Atomic Integer 내부 에서 CAS 작업 을 사 용 했 기 때문에 자물쇠 없 이 위로 점점 증가 합 니 다.어떤 사람 이 자물쇠 없 는 작업 이 나타 날 지 물 어 볼 것 입 니 다.답 은 하나 밖 에 없습니다.그것 이 빠 른 것 입 니 다.
다음은 AtomicInteger 의 사용 방법 입 니 다.
package com.example.demo.threaddemo.juc_008;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author D-L
* @Classname T01_AtomicInteger
* @Version 1.0
* @Description AtomicInteger synchronized
* @Date 2020/7/22
*/
public class T01_AtomicInteger {
// int count = 0;
AtomicInteger count = new AtomicInteger(0);
public /**synchronized*/ void m(){
for (int i = 0; i < 10000; i++) {
// count++;
count.incrementAndGet();
}
}
public static void main(String[] args) {
T01_AtomicInteger t = new T01_AtomicInteger();
List<Thread> threads = new ArrayList<>();
for (int i = 0; i < 10; i++) {
threads.add(new Thread(t::m ,"Thread" + i));
}
threads.forEach(o -> o.start());
threads.forEach(o ->{
try {
o.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
/* for (int i = 0; i < 10; i++) {
new Thread(t::m ,"Thread"+i).start();
}
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
System.out.println(t.count);
}
}
2.Atomic 류,synchronized,LongAdder 의 효율 검증 및 분석여러 개의 스 레 드 를 모 의 하여 하나의 수 를 증가 시 키 고 다 중 스 레 드 가 하나의 공유 변 수 를 증가 시 키 는 방법 은 대략 세 가지 가 있다.그들의 효율 을 검증 해 보 세 요.여기 서 거 친 테스트 를 하면 기본적으로 문 제 를 설명 할 수 있 고 구체 적 인 상황 은 실제 상황 에 따라 야 합 니 다.
첫 번 째:long count=0 사용 하기;자 물 쇠 를 넣 어 실현 하기;
두 번 째:AtomicLong 류 를 사용 하여 실현 합 니 다.
세 번 째:LongAdder 를 사용 하여 실현 합 니 다.
package com.example.demo.threaddemo.juc_008;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
/**
* @author D-L
* @Classname T02_AtomicVsSyncVsLongAdder
* @Version 1.0
* @Description Atomic synchronized LongAdder
* @Date 2020/7/22
*/
public class T02_AtomicVsSyncVsLongAdder {
static AtomicLong count1 = new AtomicLong(0L);
static Long count2 = 0L;
static LongAdder count3 = new LongAdder();
public static void main(String[] args) throws InterruptedException {
Thread [] threads = new Thread[1000];
/*-----------------------------------Atomic -----------------------------------*/
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(() ->{
for (int j = 0; j < 100000; j++) {
count1.incrementAndGet();
}
});
}
long start = System.currentTimeMillis();
for (Thread t : threads) t.start();
for (Thread t : threads) t.join();
long end = System.currentTimeMillis();
System.out.println("Atomic:" + count1.get() +"-----time:" +(end - start));
/*----------------------------------synchronized---------------------------------*/
Object lock = new Object();
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 100000; j++) {
synchronized (lock) {
count2++;
}
}
}
});
}
long start2 = System.currentTimeMillis();
for (Thread t : threads) t.start();
for (Thread t : threads) t.join();
long end2 = System.currentTimeMillis();
System.out.println("synchronized:" + count1.get() +"-----time:" +(end2 - start2));
/*-------------------------------------LongAdder----------------------------------*/
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(() ->{
for (int j = 0; j < 100000; j++) {
count3.increment();
}
});
}
long start3 = System.currentTimeMillis();
for (Thread t : threads) t.start();
for (Thread t : threads) t.join();
long end3 = System.currentTimeMillis();
System.out.println("LongAdder:" + count1.get() +"-----time:" +(end3 - start3));
}
}
/*---------------------------------- ---------------------------------*/
Atomic:100000000-----time:2096synchronized:100000000-----time:5765LongAdder:100000000-----time:515
이상 의 결 과 를 보면 병발 량 이 어느 정도 운행 효율 에 이 르 렀 다.LongAdder>AtomicLong>synchronized;이것 은 아직 대략적인 테스트 일 뿐 구체 적 으로 사용 하려 면 실제 상황 에 따라 야 한다.왜 AtomicLong 의 효율 은 synchronized 의 효율 보다 높 습 니까?
AtomicLong 의 바 텀 은 CAS 작업(잠 금 없 는 최적화)을 사용 하 는데 synchronized 는 바 텀 이 최적화 되 었 지만 병발 량 이 일정한 층 도 에 이 르 렀 고 자물쇠 의 팽창 이 존재 하 며 결국은 중량급 자물쇠 가 될 것 이 며 운영 체제 에 잠 금 자원 을 신청 해 야 하기 때문에 synchronized 의 효율 이 느 리 고 합 리 적 입 니 다.
왜 LongAdder 의 효율 은 AtomicLong 보다 높 습 니까?
롱 애 더 는 세그먼트 잠 금 이라는 개념 을 사용 해 아 토 믹 롱 보다 효율 적 이기 때문이다.
세그먼트 잠 금 은 한 배열 로 스 레 드 를 여러 그룹 으로 나 눈 다음 에 운행 이 끝 난 후에 결 과 를 누적 하 는 것 을 의미한다.예 를 들 어 1000 개의 스 레 드 가 있 고 배열 의 길 이 는 4 이다.그러면 0-250 개 를 배열 의 0 위 에 놓 고 이런 식 으로 유추 한 다음 에 네 개의 배열 에서 스 레 드 의 계산 결 과 를 누적 하면 어느 정도 시간 을 절약 하여 효율 을 높 일 수 있다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 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에 따라 라이센스가 부여됩니다.