package com.example;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicLong;
import org.junit.jupiter.api.Test;
/**
* 原子操作测试:值类型操作如++非原子性,CPU内有高速缓存,多线程非安全 java.util.concurrent.atomic包下对应有原子操作封装类 以AtomicLong自增为例,CPU消耗远远高于long自增(约2个数量级)
*
* @author yeqiang
* @since 5/28/20 8:58 AM
*/
public class AtomicOptTest {
static final long INC_LOOP_COUNT = 100000000l;
static final Semaphore semaphore = new Semaphore(0);
static long counter = 0l;
static AtomicLong atomicLong = new AtomicLong(0l);
Runnable counterIncFailFun = new Runnable() {
@Override
public void run() {
for (int i = 0; i < INC_LOOP_COUNT; i++) {
counter++;
}
semaphore.release();
}
};
Runnable counterIncSuccFun = new Runnable() {
@Override
public void run() {
for (int i = 0; i < INC_LOOP_COUNT; i++) {
atomicLong.addAndGet(1);
}
semaphore.release();
}
};
/**
* 失败的测试
*
* @throws InterruptedException
*/
@Test
public void testMultiThreadCounterIncFail() throws InterruptedException {
int THREAD_COUNT = 2;
long result = INC_LOOP_COUNT * THREAD_COUNT;
for (int i = 0; i < THREAD_COUNT; i++) {
Thread t = new Thread(counterIncFailFun);
t.start();
}
semaphore.acquire(THREAD_COUNT);
System.out.println(counter);
}
@Test
public void testMultiThreadCounterIncSucc() throws InterruptedException {
int THREAD_COUNT = 2;
long result = INC_LOOP_COUNT * THREAD_COUNT;
for (int i = 0; i < THREAD_COUNT; i++) {
Thread t = new Thread(counterIncSuccFun);
t.start();
}
semaphore.acquire(THREAD_COUNT);
System.out.println(atomicLong.get());
}
}
运行结果
结果说明:
1. 普通java long类型++操作不能保证多线程安全,由于CPU缓存,运行速度极快,CPU消耗低
2. AtomicLong addAndGet()方法具备原子性,保证结果安全,但CPU消耗极大,耗时是long ++的两个数量级