线程通信主要通过共享对字段和对象的访问来发生。 尽管这种通信方式非常高效,但它易于出现诸如线程干扰和内存一致性之类的错误。 同步是一种有助于防止此类错误的工具。

但是,同步不是免费提供的,并且在访问当前由另一个线程持有的锁或对象时会引入延迟。 等待中的线程无法使用该对象,直到另一个线程释放该对象上的锁。 这种情况称为线程争用。 它还可能导致死锁和活锁。

在本文中,我们将探讨Java提供的用于处理线程同步的不同选项。

同步要点

Java提供了一系列机制来处理基本线程同步和协调。 它支持通过同步方法和同步语句进行细粒度的对象访问同步。 基本线程协调可以通过受保护的块来完成。 所有提到的机制都是围绕获取和释放对象的固有锁定而构建的。

内在锁

每个Java对象都有一个关联的固有锁。 需要对对象的字段进行独占访问的线程必须在访问对象之前获取对象的锁,然后在完成后释放固有的锁。 其他尝试访问该对象的线程将阻塞,直到持有锁的线程将其释放为止。

同步方法

当线程调用同步方法时 ,它获取该方法对象的内在锁 ,并在方法返回时释放它。 即使该方法由于未捕获的异常而返回,也将释放该锁定。 如果以静态方法完成,则线程将获取与该类关联的类对象的锁。

同步语句

提供更细粒度的同步机制。 同步语句必须指定提供内部锁的对象。 在分离的锁对象上进行同步可以提供字段同步,而无需强制方法调用之间进行同步。

守卫的块

如前所述,受保护的块为线程协调提供了支持。 受保护的块是每个Java对象的一部分,可以使用waitnotifynotifyAll方法构造。

wait方法挂起当前线程。 当线程调用wait时,它必须拥有对象的固有锁,这就是为什么wait调用通常包装在同步方法或语句中的原因。 调用wait方法将挂起线程执行并释放锁。

在某个时刻,另一个线程将获取对象的固有锁,并调用notifyAll来通知所有线程等待发生重要事件。 在第二个线程释放锁之后,等待的线程将重新获取该锁,并通过从等待调用中返回来恢复执行。

Notify唤醒单个线程。 无法指定唤醒的具体线程,因此,仅在我们不关心哪个线程被唤醒时才有用。

Java同步器

Java还提供了五个用于通用特殊用途同步的类。

CountDownLatch

CountDownLatch类允许一个或多个线程等待,直到其他线程中的一组操作完成。 用计数编号初始化。

await方法将阻塞,直到计数达到零为止。

countDown方法减少计数。

当await方法返回时,将释放所有等待线程,并且随后的await调用将立即返回。 计数无法重置。

信号

信号量用于限制线程对特定资源的访问。 初始化具有许多许可证。

acquire方法将一直阻塞,直到获得许可并获得许可为止。

release方法添加许可,释放阻止获取者。

请注意,调用release不一定必须由称为Acquisition的线程进行。 信号量可以是公平的,也可以是不公平的 。 如果公平,则线程以FIFO方式获取许可。

尽管起初它看上去与CountDownLatch类似,但其目的却完全不同。

循环屏障

CyclicBarrier建立在各方概念的周围。 它允许线程等待彼此到达一个公共的障碍点。

await方法将阻塞,直到各方到达为止。 它的行为与CountDownLatch的逆过程相同。 N等待之后,它继续。

它支持每个障碍点运行一次的可选可运行对象。 在最后一个聚会到达之后,但在释放之前。 它通常用于更新线程之间的共享状态。 它是循环的,因为它可以在线程释放后重用

交换者

Exchanger是两个线程可以交换信息的同步点。

线程将阻塞,直到其对方显示其信息为止。 双方都发生相同的行为。

移相器

Phaser是一个可重用的屏障,类似于CountDownLatchCyclirBarrier ,但更加灵活。

在Phaser中,创建时注册方的数量不是固定的。 双方可以在通过任何注册registerbulkRegister方法。 双方可以在抵达时注销arriveAndDeregister

它提供了几种同步方法。 arriveAndAwaitAdvance方法的行为与CycleBarrier await方法的行为相同。 arrivearrivearriveAndDeregister记录到达,但不要阻塞。 awaitAdvance阻塞,直到各方到达为止。

它可以终止 ,强制所有同步方法返回。 可以通过forceTermination方法强制forceTermination

它还提供了监视其状态的支持。 值得注意的是,同步方法只能由注册方调用,而状态可以由任何调用者监视。 监视方法包括getRegisteredPartiesgetArrivedParties等。

结论

多线程绝对不是一个简单的问题,但是使用某些语言提供的工具可以更轻松地解决多线程问题。 就个人而言,我不需要每天使用所有工具,但是我认为有必要知道它们的存在以及如何提供帮助。

翻译自: https://www.javacodegeeks.com/2016/08/the-java-syncrhonisers.html

Java Syncrhonisers相关推荐

  1. java名 java_Java Syncrhonisers

    java名 java 线程通信主要通过共享对字段和对象的访问来发生. 尽管这种通信方式非常高效,但它易于出现诸如线程干扰和内存一致性之类的错误. 同步是一种有助于防止此类错误的工具. 但是,同步不是免 ...

  2. springboot实现SSE服务端主动向客户端推送数据,java服务端向客户端推送数据,kotlin模拟客户端向服务端推送数据

    SSE服务端推送 服务器向浏览器推送信息,除了 WebSocket,还有一种方法:Server-Sent Events(以下简称 SSE).本文介绍它的用法. 在很多业务场景中,会涉及到服务端向客户端 ...

  3. Java 获取当前时间之后的第一个周几,java获取当前日期的下一个周几

    Java 获取当前时间之后的第一个周几,java获取当前日期的下一个周几 //获得入参的日期 Calendar cd = Calendar.getInstance(); cd.setTime(date ...

  4. 在k8s中使用gradle构建java web项目镜像Dockerfile

    在k8s中使用gradle构建java web项目镜像Dockerfile FROM gradle:6-jdk8 AS build COPY --chown=gradle:gradle . /home ...

  5. Java | kotlin 手动注入bean,解决lateinit property loginService has not been initialized异常

    kotlin.UninitializedPropertyAccessException: lateinit property loginService has not been initialized ...

  6. SpringBoot项目使用nacos,kotlin使用nacos,java项目使用nacos,gradle项目使用nacos,maven项目使用nacos

    SpringBoot项目使用nacos kotlin demo见Gitte 一.引入依赖 提示:这里推荐使用2.2.3版本,springboot与nacos的依赖需要版本相同,否则会报错. maven ...

  7. OpenAPI使用(swagger3),Kotlin使用swagger3,Java使用swagger3,gradle、Maven使用swagger3

    OpenAPI使用(swagger3) demo见Gitte 一.背景及名词解释 OpenAPI是规范的正式名称.规范的开发工作于2015年启动,当时SmartBear(负责Swagger工具开发的公 ...

  8. Gradle错误提示:Java home supplied via ‘xxx.xxx.xxx‘ is invalid

    Gradle错误提示:Java home supplied via 'org.gradle.java.home' is invalid 描述:在使用idea采用gradle进行依赖的管理功能,当想切换 ...

  9. 查看Hotspot源码,查看java各个版本源码的网站,如何查看jdk源码

    java开发必知必会之看源码,而看源码的第一步则是找到源码

最新文章

  1. H3CSE 380笔记
  2. Hibernate 关联映射 之 多对多 关联(一)
  3. fft函数图像横坐标是什么_10分钟学会:函数图像的平移与伸缩变换
  4. 【图像处理】——Python鼠标框选ROI(感兴趣)区域并且保存(含鼠标事件)
  5. MongoDb连接表的查询
  6. mysql空值判断函数_MySQL中的ifnull()函数判断空值
  7. mysql数据库主从不同步_MySQL数据库之mysql主从数据库不同步的2种解决方法
  8. 结构方程软件Lisrel 8.7 和HLM5.5
  9. 从看《长津湖》想到的数字化转型
  10. php写幻灯片,原生JS写的幻灯片
  11. c语言开发环境win10,老司机解决win10系统搭建C语言开发环境的操作技巧
  12. MATLAB求解一元二次方程
  13. 毕业论文写作经验总结
  14. Main Menu菜单栏消失解决
  15. LSTM - 长短期记忆网络
  16. rgb 接口lcd 驱动调试
  17. Excel如何分别提取出数值整数部分和小数部分
  18. Pytorch.Dataloader 详细深度解读和微修改源代码心得
  19. 循环双链表的p所指的结点之前插入q所指结点的操作为()
  20. 「Adobe国际认证」关于Adobe Photoshop,创建和修改画笔教程?

热门文章

  1. 想要玩转实现负载均衡,你知道这些吗?
  2. Spring Bean 后置处理器
  3. Maven精选系列--介绍与安装
  4. java8 hash算法
  5. 09-一对多关系建表
  6. 【Android布局】控件布置
  7. 《四世同堂》金句摘抄(十二)
  8. (转)Spring Boot通过ImportBeanDefinitionRegistrar动态注入Bean
  9. java平台脚本+java编译器API
  10. aws实例启动失败_AWS:启动安装了APOC的Neo4j实例