CAS自定义锁及模拟高并发测试

文章简介

本文主要介绍CAS实现自定义独占锁,及模拟高并发测试检测独占锁是否线程安全。本文更偏向于后者。

独占锁

CAS+BQ+LockSupport就可以完成,这里不是重点,重点是测试。

public class ExclusiveLock {
    AtomicReference<Thread> sign = new AtomicReference();
    BlockingQueue<Thread> waiter = new LinkedBlockingQueue();

    public  void lock(){
        Thread thread = Thread.currentThread();
        while(!sign.compareAndSet(null,thread)){
            waiter.add(thread);
            //这里不可以用wait notify,因为notify不能唤醒指定的线程,只能用LockSupport
            LockSupport.park();
            waiter.remove(thread);
        }
    }

    public void unlock(){
        if(sign.compareAndSet(Thread.currentThread(),null)){
            Object[] arrs = waiter.toArray();
            for (Object obj:arrs) {
                LockSupport.unpark((Thread)obj);
            }
        }
    }
}

错误测试

这段代码虽然跑起来没有问题,每次都是10000,但是却不是真正意义的并发,因为每次for循环也是有先后顺序的,哪怕只差那么几ns,而真正的并发是同时。

    static int i;
    static ExclusiveLock lock = new ExclusiveLock();
    public static void main(String[] args) throws InterruptedException {
        int concurrent=10000;
        for(int i=0;i<concurrent;i++){
            new Thread(new Runnable() {
                @Override
                public void run(){
                        add()}
            }).start()}
        Thread.sleep(4000);
        System.out.println(i);
    }
    public static void add(){
        lock.lock();
        i++;
        lock.unlock();
    }

CountDownLatch测试

这种方式接近完美了,可是Thread.sleep(4000);这行代码是我所不能容忍的,我怎么知道到底要休眠多久。
那我们可以这样想,可不可以把CountDownLatch初始值定为concurrent+1,然后把Thread.sleep(4000);这行代码换成cdl.await();答案是不行的,因为当countDown到0的时候这10000+1个线程是同时运行的,所以打印出的值是一个很小的值。
我们接着想,可不可以在add执行完后用某个东西把他阻塞掉,等到10000个线程全部把add执行完才恢复。
请看下一个完美的案例 CountDownLatch+CyclicBarrier

    static int i;
    static ExclusiveLock lock = new ExclusiveLock();
    public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
        int concurrent=10000;
        final CountDownLatch cdl = new CountDownLatch(concurrent);
        for(int i=0;i<concurrent;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        cdl.await();//10000个线程全阻塞在这里,直到countDown到0为止
                        add();//10000个线程同时自增
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            cdl.countDown();
        }
        Thread.sleep(4000);//?
        System.out.println(i);
    }
    public static void add(){
        lock.lock();
        i++;
        lock.unlock();
    }

CountDownLatch+CyclicBarrier测试

	static int i;
    static ExclusiveLock lock = new ExclusiveLock();
    public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
        int concurrent=10000;
        final CyclicBarrier barrier = new CyclicBarrier(concurrent+1);//主线程也需要等待,所以+1
        final CountDownLatch cdl = new CountDownLatch(concurrent);
        for(int i=0;i<concurrent;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        cdl.await();//10000个线程全阻塞在这里,直到countDown到0为止
                        add();//10000个线程同时自增
                        barrier.await();//执行完后等待
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            cdl.countDown();
        }
        barrier.await();//
        System.out.println(i);
    }
    public static void add(){
        lock.lock();
        i++;
        lock.unlock();
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值