java同步手段

前言

看来很多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 ,才会往后执行。
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 一、多线程 说明下线程的状态 java中的线程一共有 5 种状态。 NEW:这种情况指的是,通过 New 关键字创...
    Java旅行者阅读 4,912评论 0 44
  • Java并发总结 1.多线程的优点 资源利用率更好 程序在某些情况下更简单 程序响应更快 2.创建线程 1.实现R...
    不会上树的猴子阅读 1,106评论 0 5
  • 打开车窗 有新鲜的空气涌进来 太阳光顺着窗户缝隙 暖暖的照在身上 没有了夏天的火热 只留下一股慵懒的味道
    朗月微光阅读 402评论 0 17
  • 我想我明白了 原来 你很爱我 原来 我的猜测和怀疑都多次欺骗我 我想我明白了 我可以创作自己的美妙生活 你来伴奏 ...
    李老灰阅读 194评论 1 0
  • 在国内的大多数城市里,有一座属于自己的房子,是身份的象征。中国人爱房子,需要房子,憧憬房子。一波波尚处于奋斗的青年...
    Olivia之歌阅读 898评论 0 1

友情链接更多精彩内容