JUC 常见的锁

一、AtomicInteger

public class T01_AtomicInteger {
   

    //不用加volatile
    public AtomicInteger count = new AtomicInteger(0);

    //不用加synchronized
    public void m() {
   
        for (int i = 0; i < 1000; i++) {
   
            //count++
            count.incrementAndGet();
        }
    }

    public static void main(String[] args) {
   
        T01_AtomicInteger t = new T01_AtomicInteger();

        List<Thread> threadList = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
   
            threadList.add(new Thread(t::m, "t" + i));
        }

        threadList.forEach((o)->{
   
            o.start();
        });

        threadList.forEach((o)->{
   
            try {
   
                o.join();
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
        });

        System.out.println(t.count);
    }

}

1、底层实现

CAS(Compare And Swap/Set)无锁优化、乐观锁

cas(V, Expected, NewValue)
if V == E
V = New
otherwise try again or fail

V:要改的值
Expected:期望当前这个值是多少
NewValue:要设置的新值
比如要改的值是3(即最开始拿到的这个值是3),当执行CAS操作时,我期望(Expected)这个值是3,是3我才修改这个值;如果当执行CAS时,不等于我期望的值3,说明这个值被其他线程改了(假如改为了4),那我就再试一次(try again)。此时我期望这个值是4,如果执行CAS操作时,没有其他的线程再次修改这个值,即和我期望的值4相等,那我再执行CAS操作,把值修改为新值。

(1) 如果在执行CAS操作的时候,在判断值是否为我期望的值后,马上有其他线程把这个值改为了其他的值,那这种情况不是依然有问题吗?

CAS操作是CPU原语支持的,也就是说CAS的操作是CPU指令级别的操作,不允许被改变。

(2)ABA问题

就是在我执行CAS操作的时候,这个值被其他的线程修改为了2,然后又改为了3,也就是中间经过了更改。如果是int这种无关系的类型,就可以不用管;如果要处理,需要加版本号,也就是这个值作任何一次的修改,版本号都加1,后面检查的时候和版本号一起检查。
(就好比 你的女朋友跟你复合时,中间又交了别的男朋友,她可能就已经变了,不再是你原来的女朋友)

(3)CAS底层是怎么做到的?

里面是通过sun.misc.Unsafe类来做的(大多数方法都是native的)。该类主要作用:直接操作JVM内存(native allocateMemory)、直接生成类实例(native allocateInstance)、直接操作变量(native getInt、native getObject)、以及CAS相关操作(native compareAndSwapObject)。该类只能通过反射或者getUnsafe得到该类的对象来使用(单例),不能直接使用。

2、SyncLong VS AtomicLong VS LongAdder

public class T02_AtomicSynclongLongAdder {
   
    private static AtomicLong count1 = new AtomicLong(0L);
    private static long count2 = 0L;
    private static LongAdder count3 = new LongAdder();

    public static void main(String[] args) throws Exception {
   
        Thread[] threads = new Thread[1000];

        //AtomicLong
        for (int i = 0; i < threads.length; i++) {
   
            threads[i] = new Thread(() -> {
   
                for (int j = 0; j < 100000; j++) {
   
                    count1.incrementAndGet();
                }
            });
        }
        long start = System.currentTimeMillis();
        for (Thread thread : threads) {
   
            thread.start();
        }
        for (Thread thread : threads) {
   
            thread.join();
        }
        long end = System.currentTimeMillis();
        System.out.println("AtomicLong: " + count1.get() + " time: " + (end - start));

        //long
        Object o = new Object();
        for (int i = 0; i < threads.length; i++) {
   
            threads[i] = new Thread(() -> {
   
                for (int j = 0; j < 100000; j++) 
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值