美文网首页
java同步手段

java同步手段

作者: 维特无忧堡 | 来源:发表于2018-07-11 22:44 被阅读0次

    前言

    看来很多java同步的各种策略,现在我们来总结一下一共有哪些呢

    正文

    1、synchronized和ReentrantLock

    每个对象都会持有一个monitor,最开始一个对象的monitor会指向null,用 synchronized修饰代码块的时候,会默认在代码块的前面和后面分别加上enter和exit指令,当执行到enter指令时就会检测 monitor 是否为空,如果是的话就会把当前线程赋给monitor,如果不是就阻塞;当执行到exit的时候就会把monitor设置为空

    ReentrantLock与synchronized不同,它是封装好的工具类,不像synchronized是基于JVM的,所以需要使用lock和unlock来手动获取与释放锁,而正是因为此则更加灵活,此外,相较于synchronized,它还有其他优点

    • 可以实现公平锁,先来先到
    • 可重入,当该线程再次试图获取锁时,自动成功
    • 带超时的获取锁尝试
    • 条件变量代替了Object的 wait/notify,变得很直观

    但并不是说synchronized一定就比ReentrantLock差,在jdk1.5之前,synchronized是个重量级锁,因为monitor指令是调用操作系统的排他锁来实现的,它要从用户态转到核心态,所以不太好,在1.6之后做了优化,例如说偏向锁、自旋锁的产生优化了synchronized的处理,所以说现在synchronized不一定比ReentrantLock性能差。

    2、CyclicBarrier 与CountDownLatch

    CountDownLatch 的功能类似一个计时器,等到我们规定的时间后就会执行,例如这个场景:假设你的系统要启动,启动之前需要做很多配置准备工作,这些任务你分别交给了几个线程去执行,当这些操作都完成之后你才能启动系统,那么怎么解决这个线程同步的问题呢?这里用CountDownLatch就很好解决,让每个子线程执行完成之后,countdown(),主线程调用await()阻塞方法,当getcount为0 的时候await就会往下执行,这样就完成了

    而CyclicBarrier 的功能类似与一辆卡车,假设车上有5个位置,要等到陆陆续续人来了,把座位坐满了才会出发,
    送完人之后就可以继续接着来一批。假设设定的5的话,那么必须在5个子线程中调用await(),之后每个线程都会往后执行,不然都会阻塞在那里,直到执行了5次await(),

    public class CyclicBarrierDemo {
        
        public static void main(String[] args) {
           new CyclicBarrierDemo().action();
    
        }
        public void action(){
            CyclicBarrier barrier = new CyclicBarrier(3);
            Thread thread = new Thread(new CyclicThread(barrier,"A"));
            thread.start();
            System.out.println("---------wait---------");
            Thread thread1 = new Thread(new CyclicThread(barrier,"B"));
            thread1.start();
        }
    
        class CyclicThread implements Runnable{
    
            private CyclicBarrier barrier;
            private String name;
            public CyclicThread(CyclicBarrier barrier,String name){
                this.barrier = barrier;
                this.name = name;
            }
            @Override
            public void run() {
                try {
                    barrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
                System.out.println(name + "-> begin");
            }
        }
    }
    

    那么我们来总结一下两者的区别的

    • CountDownLatch 无法被重用,而CyclicBarrier 可以循环使用
    • CountDownLatch 的基本操作组合是 countDown/await。调用 await 的线程阻塞等待countDown 足够的次数;CyclicBarrier 是等待所有的线程都调用了await ,才会往后执行。

    相关文章

      网友评论

          本文标题:java同步手段

          本文链接:https://www.haomeiwen.com/subject/nizqpftx.html