easy-base-concurrent | 线程安全-原子性

AtomicInteger

  • AtomicXXX:CAS、unsafe.compareAndSwapInt
@ThreadSafe
@Slf4j
public class SafeCountAtomic {
    public static int clientTotal = 5000;
    public static int threadTotal = 200;
    public static AtomicInteger count = new AtomicInteger(0);

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();
        final Semaphore semaphore = new Semaphore(threadTotal);
        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
        for (int i = 0; i < clientTotal; i++) {
            executorService.execute(() -> {
                try {
                    semaphore.acquire();
                    add();
                    semaphore.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                countDownLatch.countDown();
            });
        }

        countDownLatch.await();
        executorService.shutdown();
        log.info("count:{}", count.get()); // 5000
    }

    private static void add() {
        count.incrementAndGet();
        // count.getAndIncrement();
    }

}

源码分析
AtomicInteger.class

public final int incrementAndGet() {
    return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}

Unsafe.class

// 传入对象,
public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
           // 从主内存中获取到值
            var5 = this.getIntVolatile(var1, var2);
            // 将var1对象,工作内存中的值(var2)和主内存中的值(var5)比较,
            // 如果相等,则将该值设置为( var5 + var4),
            // 如果不相等,循环直到相等。
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
	
	// 返回主内存中的值
        return var5;
}
// JVM底层方法
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

AtomicLong和LongAdder

优劣分析:
CAS:如果竞争激烈的时候,会多次循环尝试,性能会受到一些影响
JVM对于普通类型的Long和Double变量,会将64位的读写操作拆成2个32位的操作
LongAdder在AtomicLong的基础上,将更新的压力分散,提高并行度,缺点,可能有误差。
选择:线程竞争激烈程度,高,选LongAdder,低,选AtomicLong
	   对数据的准确性要求高,选AtomicLong
package com.xiao.base.concurrent.atomic;

import com.xiao.base.concurrent.annotations.ThreadSafe;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @desc: 功能描述:()
 * @author: jianjun.xiao
 * @E-mail: xiaoxiao65535@163.com
 * @createTime: 2018/9/28 16:40
 */
@ThreadSafe
@Slf4j
public class SafeCountAtomicLong {
    public static int clientTotal = 5000;
    public static int threadTotal = 200;
    public static AtomicLong count = new AtomicLong(0);

    public static void main(String[] args) throws Exception {
        ExecutorService executorService = Executors.newCachedThreadPool();
        final Semaphore semaphore = new Semaphore(threadTotal);
        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
        for (int i = 0; i < clientTotal; i++) {
            executorService.execute(() -> {
                try {
                    semaphore.acquire();
                    add();
                    semaphore.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                countDownLatch.countDown();
            });
        }

        countDownLatch.await();
        executorService.shutdown();
        log.info("count:{}", count.get());
    }

    public static void add() {
        count.incrementAndGet();
    }
}

package com.xiao.base.concurrent.atomic;

import com.xiao.base.concurrent.annotations.ThreadSafe;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.LongAdder;

/**
 * @desc: 功能描述:()
 * @author: jianjun.xiao
 * @E-mail: xiaoxiao65535@163.com
 * @createTime: 2018/9/28 16:46
 */
@ThreadSafe
@Slf4j
public class SafeCountLongAdder {
    public static int clientTotal = 5000;
    public static int threadTotal = 200;
    public static LongAdder count = new LongAdder();

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();
        final Semaphore semaphore = new Semaphore(threadTotal);
        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
        for (int i = 0; i < clientTotal; i++) {
            executorService.execute(() -> {
                try {
                    semaphore.acquire();
                    add();
                    semaphore.release();
                } catch (Exception e) {

                }
                countDownLatch.countDown();
            });
        }

        countDownLatch.await();
        executorService.shutdown();
        log.info("count:{}", count);
    }

    public static void add() {
        count.increment();
    }
}

AtomicBoolean的CAS操作很有用(某段代码只执行一次)

package com.xiao.base.concurrent.atomic;

import com.xiao.base.concurrent.annotations.ThreadSafe;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @desc: 功能描述:()
 * @author: jianjun.xiao
 * @E-mail: xiaoxiao65535@163.com
 * @createTime: 2018/10/7 10:45
 */
@Slf4j
@ThreadSafe
public class SafeAtomicBoolean {

    private static int clientTotal = 5000;

    private static int threadTotal = 200;

    private static AtomicBoolean isHappened = new AtomicBoolean(false);

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();
        final Semaphore semaphore = new Semaphore(threadTotal);
        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
        for (int i = 0; i < clientTotal; i++) {
            executorService.execute(() -> {
                try {
                    semaphore.acquire();
                    happend();
                    semaphore.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                countDownLatch.countDown();
            });
        }

        countDownLatch.await();
        executorService.shutdown();
        log.info("{}", isHappened.get());
    }

    public static void happend() {
        if (isHappened.compareAndSet(false, true)) {
            log.info("execute");
        }
    }

}

AtomicReference

package com.xiao.base.concurrent.atomic;

import com.xiao.base.concurrent.annotations.ThreadSafe;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicReference;

/**
 * @desc: 功能描述:()
 * @author: jianjun.xiao
 * @E-mail: xiaoxiao65535@163.com
 * @createTime: 2018/9/28 17:07
 */
@ThreadSafe
@Slf4j
public class SafeAtomicReference {
    public static AtomicReference<Integer> num = new AtomicReference<>(0);

    public static void main(String[] args) {
        num.compareAndSet(0, 1); // 1
        num.compareAndSet(0, 2); // no
        num.compareAndSet(1, 3); // 3
        num.compareAndSet(1, 4); // no
        num.compareAndSet(3, 5); // 5
        log.info("count:{}", num.get()); // 5
    }

}

AtomicIntegerFieldUpdater

package com.xiao.base.concurrent.atomic;

import com.xiao.base.concurrent.annotations.ThreadSafe;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

/**
 * @desc: 功能描述:()
 * @author: jianjun.xiao
 * @E-mail: xiaoxiao65535@163.com
 * @createTime: 2018/10/7 10:29
 */
@ThreadSafe
@Slf4j
public class SafeAtomicIntegerFieldUpdater {
    // AtomicIntegerFieldUpdater : 原子性更新某个对象的某个字段,该字段必须被volatile修饰,且不能为static
    private static AtomicIntegerFieldUpdater<SafeAtomicIntegerFieldUpdater> updater
            = AtomicIntegerFieldUpdater.newUpdater(SafeAtomicIntegerFieldUpdater.class, "count");

    // 要更新的对象的值必须被volatile修饰
    @Getter
    private volatile int count = 100;

    public static void main(String[] args) {

        SafeAtomicIntegerFieldUpdater safeAtomicIntegerFieldUpdater = new SafeAtomicIntegerFieldUpdater();

        if (updater.compareAndSet(safeAtomicIntegerFieldUpdater, 100, 200)) {
            log.info("update success 1,count:{}", safeAtomicIntegerFieldUpdater.getCount());
        }

        if (updater.compareAndSet(safeAtomicIntegerFieldUpdater, 100, 200)) {
            log.info("update success 2,count:{}", safeAtomicIntegerFieldUpdater.getCount());
        } else {
            log.info("update failed");
        }
    }

}

AtomicStampedReference(解决CAS的ABA问题)

解决方法:每次更新维护一个版本号
核心方法

// stamp : 每次更新的版本号
 public boolean compareAndSet(V   expectedReference,
                                 V   newReference,
                                 int expectedStamp,
                                 int newStamp) {
        Pair<V> current = pair;
        return
            expectedReference == current.reference &&
            expectedStamp == current.stamp &&
            ((newReference == current.reference &&
              newStamp == current.stamp) ||
             casPair(current, Pair.of(newReference, newStamp)));
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值