java高并发、多线程(四)--AtomicInteger

java高并发、多线程(四)

AtomicInteger

在上一节中我们举了下面这样一个例子:

public class SynchronizedTest {

    static int count = 0;
    public synchronized static void add() {
        for (int i = 0; i < 10000; i++) {
            count++;
        }
    }

    public static void main(String[] args) {
        List<Thread> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(new Thread(SynchronizedTest::add,"Thread-"+i));
        }
        list.forEach(t->t.start());
        list.forEach(t-> {
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        System.out.println(count);
    }
}

如果我们不使用synchronized可以达到相同目的吗?

答案是肯定的,可以使用AtomicInteger类来完成相应功能。
将上述代码修改为:

	static AtomicInteger count = new AtomicInteger(0);
    public  static void add() {
        for (int i = 0; i < 10000; i++) {
            //等同于count++
            count.incrementAndGet();
        }
    }

运行结果:
在这里插入图片描述
为什么不使用synchronized,上述程序仍然能达到线程安全呢?
答案很明显在AtomicInteger类上,因为它是线程安全的,它能保证它的操作是原子性的。那它是如何保证的呢?我们来查看它的源码:
在这里插入图片描述
在这里插入图片描述
从上面可以看到,该类使用了unsafe类及其中的compareAndSwapInt方法。

  • unsafe类
    从名字上可以看出这个类是不安全的,因为它给了java像C/C++一样操作内存空间的能力。例如:
public class UnsafeTest {
    public static void main(String[] args) {
//        通过getUnsafe()方法获取unsafe对象将抛出SecurityException异常
//        但是我们发现unsafe类源码中有private static final Unsafe theUnsafe属性;因此在这里我们可以通过反射获取unsafe对象
        Field theUnsafe = null;
        Unsafe unsafe = null;
        try {
            theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            unsafe = (Unsafe)theUnsafe.get(null);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
//      创建num一个实例对象
        NUM num = new NUM();
//      通过反射获取num对象的a属性
        Field a = null;
        try {
            a = num.getClass().getDeclaredField("a");
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
//      通过unsafe获取a的值
        int anInt = unsafe.getInt(num, unsafe.objectFieldOffset(a));
        System.out.println(anInt);
//      通过unsafe修改a的值
        unsafe.putInt(num,unsafe.objectFieldOffset(a),10);
        System.out.println(num.getA());
    }
}

/**
 * 创建一个类,具有私有属性a
 */
class NUM{
    private int a;

    public NUM() {
        this.a = 1;
    }

    public int getA() {
        return a;
    }
}

运行结果:
在这里插入图片描述

  • compareAndSwapXXX()方法

CAS(Compare And Swap)是一种无锁的比较交换策略,我们通常使用的synchronized 是一种悲观锁,它所假定的是线程在运行中总会遇上冲突,因此首先就给同步代码块上锁,致使性能降低。但是CAS不用去加锁,它所使用的方式是通过比较属性值与期望值相同,那么就直接修改,不同则循环重试。在性能上要优于synchronized。在java的并发包中大多数类都使用的是该策略。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值