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 ++的兩個數量級