AtomicInteger 사용
여 기 는 AtomicInteger 를 예 로 들 면:
내부 저장 소
전체 값 을 지 켰 습 니 다. 초기 값 은 0 입 니 다.다 중 스 레 드 작업 을 고려 하여 volatile 을 사용 하여 가시 성 을 확보 합 니 다.
private volatile int value;
단독 할당 작업
구조 함수 설정:
public AtomicInteger(int initialValue) {
value = initialValue;
}
Setter:
public final void set(int newValue) {
value = newValue;
}
지연 할당:
public final void lazySet(int newValue) {
unsafe.putOrderedInt(this, valueOffset, newValue);
}
가 져 오기 및 할당 복합 작업:
Getter:
public final int get() {
return value;
}
원래 값 가 져 오기 및 새 값 설정:
public final int getAndSet(int newValue) {
for (;;) {
int current = get();
if (compareAndSet(current, newValue))
return current;
}
}
원래 값 가 져 오기 및 자동 증가:
public final int getAndIncrement() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return current;
}
}
원래 값 가 져 오기 및 자동 감소:
public final int getAndDecrement() {
for (;;) {
int current = get();
int next = current - 1;
if (compareAndSet(current, next))
return current;
}
}
원래 값 가 져 오기 및 지정 값 추가:
dela 는 마이너스 로 getAndSubtract 기능 을 실현 할 수 있 습 니 다.
public final int getAndAdd(int delta) {
for (;;) {
int current = get();
int next = current + delta;
if (compareAndSet(current, next))
return current;
}
}
자동 증가 및 새 값 가 져 오기:
public final int incrementAndGet() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
자동 감소 및 새 값 가 져 오기:
public final int decrementAndGet() {
for (;;) {
int current = get();
int next = current - 1;
if (compareAndSet(current, next))
return next;
}
}
지정 한 값 을 추가 하고 새 값 가 져 오기:
이와 같이 델 타 는 마이너스 로 subtractAndGet 기능 을 실현 할 수 있다
public final int addAndGet(int delta) {
for (;;) {
int current = get();
int next = current + delta;
if (compareAndSet(current, next))
return next;
}
}
이 를 통 해 알 수 있 듯 이 위의 방법 은 비교적 유사 하 다. copare Andset 방법 을 순환 적 으로 호출 하고 성공 하면 되 돌아 오 는 것 이다.
compreAndSet 방법 보기:
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
또한, weakCompare AndSet 방법 도 제공 하 였 으 며, 호출 된 unsafe 방법 은 위 와 같 습 니 다.
public final boolean weakCompareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
성능 테스트
1. synchronized 와 비교 하여 단일 스 레 드 는 1000 w 회 자체 증가 작업 을 수행 합 니 다.
public class AtomicIntegerSynchTest {
private int value;
public AtomicIntegerSynchTest(int value) {
this.value = value;
}
public synchronized int increase() {
return value++;
}
public static void main(String[] args) {
long start = System.currentTimeMillis();
AtomicIntegerSynchTest test = new AtomicIntegerSynchTest(0);
for (int i = 0; i < 10000000; i++) {
test.increase();
}
long end = System.currentTimeMillis();
System.out.println("Synch elapsed: " + (end - start) + "ms");
long start2 = System.currentTimeMillis();
AtomicInteger atomicInt = new AtomicInteger(0);
for (int i = 0; i < 10000000; i++) {
atomicInt.incrementAndGet();
}
long end2 = System.currentTimeMillis();
System.out.println("Atomic elapsed: " + (end2 - start2) + "ms");
}
}
출력:
Synch elapsed: 383ms
Atomic elapsed: 208 ms (단일 스 레 드 환경 에서 Atomic Integer 는 동기 화 성능 보다 약간 좋 습 니 다)
2. 다 중 스 레 드 여러 번 조작:
여 기 는 100 개의 스 레 드 를 사용 하여 스 레 드 마다 10w 번 의 자체 증가 작업 을 수행 합 니 다. 100 개의 스 레 드 를 동시에 실행 하 는 데 걸 리 는 시간 을 통계 하기 위해 Count Downlatch 를 사용 하여 조 화 를 이 룹 니 다.
public class AtomicIntegerMultiThreadTest {
private /*volatile*/ int value;
public AtomicIntegerMultiThreadTest(int value) {
this.value = value;
}
public synchronized int increase() {
return value++;
}
public int unSyncIncrease() {
return value++;
}
public int get() {
return value;
}
public static void main(String[] args) throws InterruptedException {
long start = System.currentTimeMillis();
final CountDownLatch latch = new CountDownLatch(100);
final AtomicIntegerMultiThreadTest test = new AtomicIntegerMultiThreadTest(0);
for (int i = 0; i < 100; i++) {
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100000; i++) {
test.increase();
//test.unSyncIncrease();
}
latch.countDown();
}
}).start();
}
latch.await();
long end = System.currentTimeMillis();
System.out.println("Synch elapsed: " + (end - start) + "ms, value=" + test.get());
long start2 = System.currentTimeMillis();
final CountDownLatch latch2 = new CountDownLatch(100);
final AtomicInteger atomicInt = new AtomicInteger(0);
for (int i = 0; i < 100; i++) {
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100000; i++) {
atomicInt.incrementAndGet();
}
latch2.countDown();
}
}).start();
}
latch2.await();
long end2 = System.currentTimeMillis();
System.out.println("Atomic elapsed: " + (end2 - start2) + "ms, value=" + atomicInt.get());
}
}
출력:
Synch elapsed: 1921ms, value=10000000
Atomic elapsed: 353 ms, value = 10000000 (AtomicInteger 의 성능 은 synchronized 의 5 배가 넘 습 니 다)
value 에 volatile 수식 자 를 추가 할 때:
Synch elapsed: 2268 ms, value = 10000000 (volatile 코드 정렬 금지, 어느 정도 성능 저하)
Atomic elapsed: 337ms, value=10000000
동기 화 되 지 않 은 자동 증가 방법 unSyncIncrease 를 호출 할 때:
Synch elapsed: 216 ms, value = 5852266 (비원 자 조작 이 동기 화 되 지 않 아 결과 오류 발생)
Atomic elapsed: 349ms, value=10000000
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.