如何在Java中同步工作

首先, 这是一个示例 :

public class Deadlock { static class Friend { private final String name; public Friend(String name) { this.name = name; } public String getName() { return this.name; } public synchronized void bow(Friend bower) { System.out.format("%s: %s has bowed to me!%n", this.name, bower.getName()); bower.bowBack(this); } public synchronized void bowBack(Friend bower) { System.out.format("%s: %s has bowed back to me!%n", this.name, bower.getName()); } } public static void main(String[] args) { final Friend alphonse = new Friend("Alphonse"); final Friend gaston = new Friend("Gaston"); new Thread(new Runnable() { public void run() { alphonse.bow(gaston); } }).start(); new Thread(new Runnable() { public void run() { gaston.bow(alphonse); } }).start(); } }

我得不到的是堵塞的发生。 主函数启动两个线程,每个线程开始自己的弓。

什么是“同步”块? 为同一个对象运行同样的function(正如我原来的想法)? 同一个类的所有对象的相同的function? 同一个对象的所有同步函数? 同一类的所有对象的所有同步函数?

帮帮我。

在Java中,每个Object提供了一个线程synchronize或locking的能力。 当一个方法被同步时,该方法使用它的对象实例作为锁。 在你的例子中,方法bow和bowBack是synchronized ,并且都在同一个class级Friend 。 这意味着执行这些方法的任何线程都将在Friend实例上同步它的锁。

导致死锁的一系列事件是:

第一个线程开始调用alphonse.bow(gaston) ,它在alphonse Friend对象上synchronized 。 这意味着线程必须从这个对象获取锁。

第二个线程开始调用gaston.bow(alphonse) ,它在gaston Friend对象上synchronized 。 这意味着线程必须从这个对象获取锁。

现在开始的第一个线程调用了bowback并等待gaston上的锁被释放。

现在开始的第二个线程调用bowback并等待alphonse上的锁被释放。

要更详细地显示事件的顺序:

main()开始在主Therad中执行(称之为Thread#1),创build两个Friend实例。 到现在为止还挺好。

主线程使用代码new Thread(new Runnable() { ... Thread#2调用alphonse.bow(gaston) ,它在alphonse Friend对象上synchronized来启动它的第一个新线程(称为线程2)。线程#2因此获得了对于alphonse对象的“locking”并进入了bow法。

时间片发生在这里,原来的线程有机会做更多的处理。

主线程开始第二个新线程(称为线程#3),就像第一个线程一样。 线程#3调用gaston.bow(alphonse) ,它在gaston Friend对象上同步。 由于没有人获得gaston对象实例的“locking”,所以线程#3成功获取该锁并进入bow方法。

时间片发生在这里,线程#2有机会做更多的处理。

线程#2现在调用bower.bowBack(this); 与bower是gaston的例子的gaston 。 这是gaston.bowBack(alphonse)的调用的逻辑等价物。 因此,这个方法在gaston实例上是synchronized的。 该对象的锁已经被获取,并被另一个线程(线程#3)保存。 因此,线程#2必须等待gaston上的锁被释放。 线程处于等待状态,允许线程3进一步执行。

线程#3现在调用bowback ,在这种情况下在逻辑上与调用alphonse.bowBack(gaston) 。 为此,需要获取alphonse实例的锁,但该锁由Thread#2保存。 此线程现在处于等待状态。

而你现在处于一个线程无法执行的位置。 线程#2和线程#3正在等待一个锁被释放。 但是没有一个线程正在进行,这两个锁都不能被释放。 但是,没有一个锁被释放,任何线程都不能取得进展。

因此:僵局!

死锁通常取决于事件发生的特定顺序,由于难以重现,可能难以debugging。

同步有两个作用 :

首先,同一个对象上的两个同步方法的调用是不可能交错的。 当一个线程正在执行一个对象的同步方法时,所有其他调用同一对象的同步方法的线程将阻塞(挂起执行),直到第一个线程完成对象。

其次,当一个同步的方法退出时,它会自动build立一个与先前同步对象的任何后续调用同步方法的before-before关系。 这保证了对所有线程都可见的对象状态的改变。

简而言之,它会阻止对同一个对象的同步方法的任何调用。

同一个对象的所有同步函数。 标记一个方法“synchronized”与在方法的整个内容中放置一个“synchronized(this){”方块非常相似。 我不说“相同”的原因是因为我不知道编译器是否发出相同的字节码,但AFAIK定义的运行时效果是相同的。

死锁是一个经典的locking反转。 一个线程lockingalphonse。 然后(或同时在多核系统上)另一个线程lockinggaston。 这部分要求线程的调度恰好在正确的点交错。

然后,每个线程(以任何顺序或同时)尝试获取已由另一个线程保持的锁,从而每个线程都进入hibernate状态。 直到另一个释放它的锁,它们都不会唤醒,但是直到唤醒(或终止)它们都不会释放它的锁。

synchronized方法和把所有这些方法的代码封装成一样

synchronized(this) { /// code here ... }

块。

对于给定的对象实例o ,一次只有一个线程可以运行任何同步的(o)块。 每一个其他的线程都会试图嚎,大哭,直到运行该块的线程(具有同步的锁 )退出该块(放弃锁)。

在你的情况下,当Alphonse开始在线程1中鞠躬时,发生死锁,从而进入同步块。 线程1然后被系统交换出去,所以线程2可以启动,让Gaston鞠躬。 但加斯顿还不能回头,因为它在阿尔方斯上同步,而线程1已经有了这个锁。 它将因此等待线程1离开该块。 系统然后将交换线程1,这将尝试让Alphonse回头。 除了不能这样做,因为线程2在Gaston上有同步locking。 这两个线程现在都卡住了,等待另一个完成鞠躬,才能够回头…

java中为什么同步_如何在Java中同步工作相关推荐

  1. java 线程中创建线程_如何在Java 8中创建线程安全的ConcurrentHashSet?

    java 线程中创建线程 在JDK 8之前,还没有办法在Java中创建大型的线程安全的ConcurrentHashSet. java.util.concurrent包甚至没有一个名为Concurren ...

  2. java中转json字符串_如何在Java中转义JSON字符串-Eclipse IDE技巧

    java中转json字符串 在Java应用程序中工作或进行JSON解析时,通常很常见的做法是从某些资源(例如RESTful Web服务)中复制粘贴JSON字符串,然后使用Jackson库解析JSON. ...

  3. java整数的因式分解_如何在Java中找到整数的质数-因式分解

    java整数的因式分解 编程课程中的常见家庭作业/任务之一是关于Prime Factorization. 要求您编写一个程序以找到给定整数的素因子 . 一个数字的素数因子是将精确地除以给定数字的所有素 ...

  4. java swing 列表框_如何在Swing中使用列表框?

    下面的示例展示了如何在Java Swing应用程序中使用标准列表框. 使用以下API - JList - 创建标准列表. JList.setSelectedIndex(index); - 选择项目. ...

  5. Java poi 列移动_如何在java xssf中移動列poi

    如何將現有列數據和格式化到Apache POI中的下一列並將下一列移到右側.如何在java xssf中移動列poi 我試過了. 讓說我的代碼是這樣... XSSFCell oldCell = work ...

  6. java文件中获取创建日期_如何在Java中获取文件的上次修改日期

    java文件中获取创建日期 Sometimes we need to get the file last modified date in Java, usually for listeners li ...

  7. java 精确到微妙_如何在Java中以微秒精度测量时间?

    我在Internet上看到应该使用System.nanoTime(),但这对我不起作用-它为我提供了毫秒级的时间.我只需要函数执行前后的微秒,就可以知道需要多长时间.我正在使用Windows XP. ...

  8. java adt怎么使用_如何在eclipse中添加android ADT ADT插件的安装图文教程

    对于程序开发的学者来说,eclipse并不陌生,它为我们提供了一个非常广阔的平台来开发程序.同样我们也可以用它来开发android程序.但是在eclipse中并不能直接开发android程序,需要我们 ...

  9. java 千位分隔符_如何在Java中设置千位分隔符?

    问题 如何在Java中设置千位分隔符?我有BigDecimal的String表示,我想设置千位分隔符并返回String. #1 热门回答(180 赞) 你可以使用格式功能","; ...

最新文章

  1. mybatis入门(四)----输入映射和输出映射
  2. WEBGL学习【八】模型视图投影矩阵
  3. zend optimizer php5.5,PHP_PHP5.3以上版本安装ZendOptimizer扩展,现在很多PHP程序都需要ZendOptimi - phpStudy...
  4. java 传入多个参数时报Parameter 'XXX' not found. Available parameters are [arg1, arg0, param1,... 解决方案...
  5. xss绕过字符过滤_XSS绕过实战练习
  6. c语言二维数组中的周边,【C语言】二维数组中的查找,杨氏矩阵
  7. java打印条形码Code128C
  8. 电脑音量图标不见了,该如何找回?
  9. Atitit Immutability 和final的优点
  10. 计算机体系结构与组成的区别
  11. 进行桌面共享软件开发的市场前景如何
  12. ocx注册以及检测(转)
  13. WIN10+ubuntu16.04双系统卸载重装
  14. uni-app 对接企业微信登录
  15. QQ空间 安卓App热补丁动态修复技术介绍
  16. mmclassification使用步骤与心得/ACCV实验记录
  17. 微信小程序图片裁剪插件image-cropper
  18. 导数和积分的转换关系
  19. 嵌入式开发模拟红外测距仪---UDP通信实现无线装置
  20. 加密软件 PGP安装教程。

热门文章

  1. 十七 Ajax校验用户名功能
  2. import和class关键字的区别
  3. Oracle11g数据库审计功能的关闭和开启
  4. 在线JSON美化格式化工具
  5. 2019 第二周 开发笔记
  6. 用.net中的SqlBulkCopy类批量复制数据 (转载)
  7. VDI序曲三十 APP-V4.6SP1之OFFICE07补丁升级
  8. 为什么程序要从0开始计数
  9. Binary Tree Paths
  10. 【DAY8】关于多线程的练习