Java原始类型的非线程安全以及AtomicInteger

  • 首先,Java的原始数据类型(primitive datatypes),如short、int、double、long、boolean这些是非线程安全的;
  • Java自带的线程安全的基本类型包括: AtomicInteger, AtomicLong, AtomicBoolean, AtomicIntegerArray,AtomicLongArray等

实验,验证int类型是非线程安全的:
300个线程,每个线程对共享变量 count 进行 5000 次 ++ 操作
测试代码:

public class PriThreadNotSafety extends Thread{
    static int count = 0;
    public void run(){
        for (int k = 0; k < 5000; k++){
            count++;
        }
    }

    public static void main(String[] args) {

        for (int i = 0;i < 300; i++){
            new PriThreadNotSafety().start();
        }
        // 休眠10秒,以确保线程都已启动
        try {
            Thread.sleep(1000*10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(count);
    }
}
  • int 作为基本类型,直接存储在内存栈,且对其进行+,-操作以及++,–操作都不是原子操作,都有可能被其他线程抢断,所以不是线程安全
  • int 用于单线程变量存取,开销小,速度快

期望输出150000,最后输出的是1493602

线程安全版

public class AtomicThreadSafety extends Thread {
    private static AtomicInteger atomicInteger = new AtomicInteger(1);
    static Integer count = Integer.valueOf(0);

    @Override
    public void run() {
        for (int i = 0; i < 5000; i++) {
            // getAndIncrement: 先获得值,再自增1,返回值为自增前的值
            count = atomicInteger.getAndIncrement();
        }
    }

    public static void main(String[] args) {
        for (int k =0; k < 300; k++){
            new AtomicThreadSafety().start();
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        int excepted = 1500000;
        int result = count;
        Assert.assertEquals(excepted,result); // True
    }

返回结果1500000

  • AtomicInteger类中有有一个变量valueOffset,用来描述AtomicInteger类中value的内存位置 。

  • 当需要变量的值改变的时候,先通过get()得到valueOffset位置的值,也即当前value的值.给该值进行增加,并赋给next

  • compareAndSet()比较之前取到的value的值当前有没有改变,若没有改变的话,就将next的值赋给value,倘若和之前的值相比的话发生变化的话,则重新一次循环,直到存取成功,通过这样的方式能够保证该变量是线程安全的

  • value使用了volatile关键字,使得多个线程可以共享变量,使用volatile将使得VM优化失去作用,在线程数特别大时,效率会较低。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值