java中的同步方式大致可以分为 :
- synchronized
- ReentrantLock
- Semaphore
- CountDownLatch
- CyclicBarrier
- Phaser
我们接下来逐一介绍
1.synchronized 是最基础的一个同步方法他是jvm提供并且控制的 他的工作原理就是加锁 一段时间内只能有一个线程进行操作 synchronized是java 中最基础 、最重的一个锁(即使jvm对其进行了大量优化)不适合用在高并发的场景中
synchronized 可以锁 静态方法、方法、代码块 ,锁的粒度逐级减小 在使用synchronized 的时候能用小粒度的不要用大粒度的 ,阿里开发手册上也给出了建议:
一下是具体用法:
2.ReentrantLock
ReentrantLock 是开发中用的比较多的一个同步方法(锁)
基本用法如下
在lock()和 unlock() 之间的代码是线程安全的
3.Semaphore(信号量)
Semaphore 的作用是用来限制线程访问量的,比如说一个资源可以承受10个线程的同时访问 再多就扛不住了 那么这个时候做为程序员要做的就应该在业务层面进行限制(老板不舍得加钱买服务器咱们也没办法)这个时候就可以使用Semaphore 来进行限制
具体用法如下:
比如说三个线程获取了许可但是业务没有处理完那么其他线程就进不来只能等有许可释放之后继续获取许可后才能进入 。
3CountDownLatch(闭锁/门栓锁)
不知道大家在使用多线程的时候会不会遇到这种情况,好几个子线程执行任务 的时候主线程是不会停下来的 但是主线程接下来的操作要等子线程都执行完之后才能正确进行要不然就会报错,
CountDownLatch 就可以满足这一要求 ,请看如下代码:
执行结果:
//该方法会阻塞主线程 countDownLatch.await(10, TimeUnit.MINUTES);
await() 会阻塞主线程然后等待其他子线程执行完成之后或者超出了最大等待时间之后 主线程就会继续往下执行 。
大家可以看一下下面这张图加深一下理解
不同的线程执行任务的速度不同,但是有时候我们需要所有线程都完成之后每个任务才能进行下一步这个时候就要用到 CountDownLatch,所有线程到达图中CountDownLatch后才会继续向下执行
5.CyclicBarrier
CyclicBarrier 翻译成 循环栅栏 不过我比较喜欢叫他 循环屏障 之所以喜欢这么翻译是因为 循环屏障 比较符合 .CyclicBarrier 功能和作用
其实 CyclicBarrier 和 CountDownLatch非常相似大家可以类比记忆 大家可以把 Barrier 认为是CountDownLatch 而CyclicBarrier 多了个Cyclic(循环),前面介绍过来 CountDownLatch 是让多个线程全部阻隔到某一点之后才能继续 而CyclicBarrier 可以多次阻隔,如下图
也就是说CountDownLatch只能阻隔一次而CyclicBarrier可以阻隔多次
具体用法如下:
运行结果:
需要注意的是线程的数量一样和屏障阻挡的数量一致要不然就会生效我在这里设置的是2
CyclicBarrier 和 CountDownLatch 最大的区别在于 CountDownLatch 用过一次之后就结束了而CyclicBarrier 还可以循环使用
6.Phaser
Phaser 、CyclicBarrier、 CountDownLatch 这三者的作用相似,区别在于Phaser 可以动态的决定要协调的线程数量而不是直接写死
具体用法:
运行结果:
假设一下这位个线程就是五个任务 如果说每个任务完成之后都有啊单独做一些操作 那么这个时候就可以用Phaser 来进行判断 线程什么时候完成 从而进行对应的操作。
以上就是java 的各种同步方式,我只是简单的介绍了一下并没有深入分析实现原理 以后我会单独写一写他们的原理。
少年易老难成事,莫向光阴惰寸功。
ok,大家加油!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ri-ji/43503.html