首页 > 技术文章 > JUC 并发编程--12, 使用AtomicInteger 实现一把锁(排队自旋锁), 代码演示

lvcai 2020-09-21 11:38 原文

前面 使用自旋锁实现了一把锁,(请看 第5篇)

volatile 三大特性: 可见性, 不保证原子性, 禁止指令重排
为了解决 volatile不保证原子性的问题, 引入了原子类, AtomicInteger, 底层是使用了 CAS 直接变成汇编指令操作硬件,从而解决了 原子性的问题
而 Lock 类的底层实现是 AQS 和CAS,
这里使用 AtomicInteger的特性和自旋锁来实现一把 排队自旋锁 锁:

  class AtomicLock {
    private AtomicInteger serviceNum = new AtomicInteger();//等待者
    private AtomicInteger ticketNum = new AtomicInteger();//排队号

    public int atomicLock() {
        // 排队号加1
        int myTicketNum = ticketNum.getAndIncrement();
        //只要 排队号和 等待着的号不同,等待者就一直循环,  如果相同,就返回排队号,  这里相当于加锁成功
        while (serviceNum.get() != myTicketNum) {
        }
        System.out.println(Thread.currentThread().getName() + "加锁成功");
        return myTicketNum;
    }

    public void atomicUnlock(int num) {
        // 如果要解锁,就将排队号 +1, 并设置回等待者
        int next = num + 1;
        serviceNum.compareAndSet(num, next);
        System.out.println(Thread.currentThread().getName() + "解锁成功");
    }

    static int num = 0;
    public static void main(String[] args) throws InterruptedException {
        /**
         * 这个锁的缺点是: 如果线程很多, 这么多线程都要操作 同一个Atomicinteger,  且为了保证 各个线程的工作缓存中的数据一致性,
         * 会频繁的 在工作缓存和 主存之间进行通信,,造成系统总线和主存之间繁重的流量, 进而降低系统的性能
         *
         * 但是多处理器系统上,每个进程/线程占用的处理器都在读写同一个变量serviceNum ,每次读写操作都必须在多个处理器缓存之间进行缓存同步,
         * 这会导致繁重的系统总线和内存的流量,大大降低系统整体的性能。
         * 如何解决:  使用  CLH锁和MCS锁
         */
        AtomicLock atomicLock = new AtomicLock();
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                int j = atomicLock.atomicLock();
                System.out.println(Thread.currentThread().getName() + "操作开始: num: " + num);
                for (int k = 0; k < 20; k++) {
                    num++;
                }
                System.out.println(Thread.currentThread().getName() + "操作结束: num: " + num);
                atomicLock.atomicUnlock(j);
            },"线程"+i).start();
        }

        TimeUnit.SECONDS.sleep(3);
        System.out.println("最终结果num: "+num);
    }
}

运行结果:

CLH锁和 MCS锁, 这个是目前写的比较好的博客
https://www.jianshu.com/p/1b1b44e84394

推荐阅读