Java 同步块(synchronized block)用来标记方法或者代码块是同步的。Java同步块用来避免竞争。本文介绍以下内容:

Java同步关键字(synchronzied)

实例方法同步

静态方法同步

实例方法中同步块

静态方法中同步块

Java同步示例

Java同步关键字(synchronized)

Java中的同步块用synchronized标记。同步块在Java中是同步在某个对象上。所有同步在一个对象上的同步块在同时只能被一个线程进入并执行操作。所有其他等待进入该同步块的线程将被阻塞,直到执行该同步块中的线程退出。

有四种不同的同步块:

实例方法

静态方法

实例方法中的同步块

静态方法中的同步块

上述同步块都同步在不同对象上。实际需要那种同步块视具体情况而定。

实例方法同步

下面是一个同步的实例方法:

1 public synchronized void add(intvalue){2   this.count +=value;3 }

注意在方法声明中同步(synchronized )关键字。这告诉Java该方法是同步的。

Java实例方法同步是同步在拥有该方法的对象上。这样,每个实例其方法同步都同步在不同的对象上,即该方法所属的实例。只有一个线程能够在实例方法同步块中运行。如果有多个实例存在,那么一个线程一次可以在一个实例同步块中执行操作。一个实例一个线程。

静态方法同步

静态方法同步和实例方法同步方法一样,也使用synchronized 关键字。Java静态方法同步如下示例:

1 public static synchronized void add(intvalue){2 count +=value;3 }

同样,这里synchronized 关键字告诉Java这个方法是同步的。

静态方法的同步是指同步在该方法所在的类对象上。因为在Java虚拟机中一个类只能对应一个类对象,所以同时只允许一个线程执行同一个类中的静态同步方法。

对于不同类中的静态同步方法,一个线程可以执行每个类中的静态同步方法而无需等待。不管类中的那个静态同步方法被调用,一个类只能由一个线程同时执行。

实例方法中的同步块

有时你不需要同步整个方法,而是同步方法中的一部分。Java可以对方法的一部分进行同步。

在非同步的Java方法中的同步块的例子如下所示:

1 public void add(intvalue){2

3 synchronized(this){4 this.count +=value;5 }6 }

示例使用Java同步块构造器来标记一块代码是同步的。该代码在执行时和同步方法一样。

注意Java同步块构造器用括号将对象括起来。在上例中,使用了“this”,即为调用add方法的实例本身。在同步构造器中用括号括起来的对象叫做监视器对象。上述代码使用监视器对象同步,同步实例方法使用调用方法本身的实例作为监视器对象。

一次只有一个线程能够在同步于同一个监视器对象的Java方法内执行。

下面两个例子都同步他们所调用的实例对象上,因此他们在同步的执行效果上是等效的。

1 public classMyClass {2

3 public synchronized voidlog1(String msg1, String msg2){4 log.writeln(msg1);5 log.writeln(msg2);6 }7

8 public voidlog2(String msg1, String msg2){9 synchronized(this){10 log.writeln(msg1);11 log.writeln(msg2);12 }13 }14 }

在上例中,每次只有一个线程能够在两个同步块中任意一个方法内执行。

如果第二个同步块不是同步在this实例对象上,那么两个方法可以被线程同时执行。

静态方法中的同步块

和上面类似,下面是两个静态方法同步的例子。这些方法同步在该方法所属的类对象上。

1 public classMyClass {2 public static synchronized voidlog1(String msg1, String msg2){3 log.writeln(msg1);4 log.writeln(msg2);5 }6

7 public static voidlog2(String msg1, String msg2){8 synchronized(MyClass.class){9 log.writeln(msg1);10 log.writeln(msg2);11 }12 }13 }

这两个方法不允许同时被线程访问。

如果第二个同步块不是同步在MyClass.class这个对象上。那么这两个方法可以同时被线程访问。

Java同步实例

在下面例子中,启动了两个线程,都调用Counter类同一个实例的add方法。因为同步在该方法所属的实例上,所以同时只能有一个线程访问该方法。

1 public classCounter{2 long count = 0;3 public synchronized void add(longvalue){4 this.count +=value;5 }6 }7

8 public class CounterThread extendsThread{9 protected Counter counter = null;10

11 publicCounterThread(Counter counter){12 this.counter =counter;13 }14

15 public voidrun() {16 for(int i=0; i<10; i++){17 counter.add(i);18 }19 }20 }21

22 public classExample {23

24 public static voidmain(String[] args){25 Counter counter = newCounter();26 Thread threadA = newCounterThread(counter);27 Thread threadB = newCounterThread(counter);28

29 threadA.start();30 threadB.start();31 }32 }

创建了两个线程。他们的构造器引用同一个Counter实例。Counter.add方法是同步在实例上,是因为add方法是实例方法并且被标记上synchronized关键字。因此每次只允许一个线程调用该方法。另外一个线程必须要等到第一个线程退出add()方法时,才能继续执行方法。

如果两个线程引用了两个不同的Counter实例,那么他们可以同时调用add()方法。这些方法调用了不同的对象,因此这些方法也就同步在不同的对象上。这些方法调用将不会被阻塞。如下面这个例子所示:

1 public classExample {2

3 public static voidmain(String[] args){4 Counter counterA = newCounter();5 Counter counterB = newCounter();6 Thread threadA = newCounterThread(counterA);7 Thread threadB = newCounterThread(counterB);8

9 threadA.start();10 threadB.start();11 }12 }

注意这两个线程,threadA和threadB,不再引用同一个counter实例。CounterA和counterB的add方法同步在他们所属的对象上。调用counterA的add方法将不会阻塞调用counterB的add方法。

java 代码同步_Java同步代码块 转相关推荐

  1. java每一个小时同步_Java同步块(synchronized block)使用详解

    Java 同步块(synchronized block)用来标记方法或者代码块是同步的.Java同步块用来避免竞争.本文介绍以下内容: Java同步关键字(synchronzied) 实例方法同步 静 ...

  2. java入栈_java中代码块的执行,也会有入栈的步骤吗?

    首先这个问题很有意思,不过题主没具体指明放在何处的代码块. 这里至少有三种情况,第一种就是在普通的方法里面,第二种是实例初始化代码块,第三种是静态初始化代码块. 第一种情况 使用javap反汇编了一下 ...

  3. java linux 时区_java同步/设置Linux系统时间

    java设置/同步Linux系统时间 在网上看了很多,试了很多,不知道是他们的环境不同还是啥原因,很少成功 下面我就把我的测试成功的代码贴出来,让同行们少走弯路,如果实验不成功,可以给我留言 我帮助你 ...

  4. java底层机制_Java同步机制的底层实现

    在多线程编程中我们会遇到很多需要使用线程同步机制去解决的并发问题,而这些同步机制就是多线程编程中影响正确性和运行效率的重中之重.这不禁让我感到好奇,这些同步机制是如何实现的呢?好奇心是进步的源泉,就让 ...

  5. java redis的同步_java同步系列之redis分布式锁进化史

    标题: 死磕 java同步系列之redis分布式锁进化史 - 彤哥读源码 - 博客园 转帖原地址: https://www.cnblogs.com/tong-yuan/p/11621361.html ...

  6. java编译器代码检查_java 命名代码检查-注解处理器

    命名代码检查 根据 中第6.8节的要求, Java 程序命名应当符合下列格式的书写规范: 类 ( 或接口 ) : 符合驼式命名法, 首字母大写. 方法 : 符合驼式命名法,首字母小写 字段 :类或实例 ...

  7. java 静态方法同步_Java – 同步静态方法

    这是我的测试代码,表明你是对的,这篇文章有点过分谨慎: class Y { static synchronized void staticSleep() { System.out.println(&q ...

  8. java线程代码实现_Java 多线程代码实现讲解

    作为一个完全面向对象的语言,Java提供了类 java.lang.Thread 来方便多线程编程,这个类提供了大量的方法来方便我们控制自己的各个线程.那么如何提供给 Java 我们要线程执行的代码呢? ...

  9. java 微型数据库_Java 9代码工具:使用Java微型基准测试工具的实践会话

    java 微型数据库 用肉眼看,基准测试似乎只是确定执行某些代码需要花费多长时间的简单问题. 但是,通常情况下,这是幼稚的方法. 提供具有准确和可重复结果的有意义的基准并非易事. 在本文中,我们将向您 ...

最新文章

  1. 5秒到1秒,记一次效果“非常”显著的性能优化
  2. Java中实现多线程关键词整理
  3. Eclipse中tomcat更改部署路径 deply path
  4. 基于官方镜像MySQL做自定义业务扩充镜像
  5. Databricks:2015 Spark调查报告(部分译文)
  6. sap实施和开发哪个前景_2021年了!还不知道 SAP顾问的职业前景?
  7. CF374 Maxim and Array
  8. HH SaaS电商系统的商品销售分区功能模块设计
  9. 利用python做一个小游戏_如何使用python做一个简单的猜数字的小游戏
  10. python py2exe_转:py2exe 生成 python 可执行文件
  11. MiniDao_1.6-SNAPSHOT 版本发布,轻量级Java持久化框架
  12. 项目以任务还是以功能为中心?
  13. 【分享】regsvr32 不是内部或外部命令,也不是可运行的程序或批处理文件
  14. xpath抓取html不完全,scrapy的xpath是否取HTML标签的情况分析
  15. 【色彩管理】ICC曲线制作教程
  16. sql中别名as,不写,以及使用双引号总结
  17. 国际商业分析师CBAP认证与PMI-PBA认证的区别——上海信息化培训中心
  18. BH1750 传感器实战教学 —— 硬件设计篇
  19. sort函数和sorted函数的异同
  20. C++:66---特殊工具与技术之(不可移植的特性:位域、volatile、extern “C“链接提示)

热门文章

  1. SQL Server 2012如何打开2016的profiler文件
  2. 从.Net框架Bug的提交到修复代码成功合并到.NET CoreFX主线
  3. 站在巨人肩上的.NET Core 2.1
  4. ASP.NET Core 2.0 支付宝当面付之扫码支付
  5. 跨平台应用集成(在ASP.NET Core MVC 应用程序中集成 Microsoft Graph)
  6. 红帽、微软和 Codenvy 联合推出语言服务器协定(Language Server Protocol,LSP)项目
  7. 复盘Build 2016:不要错过微软给.NET开发者的这些福利
  8. php symfony urlmatcher-gt;match,symfony路由组件(The Routing Component)
  9. python异或运算怎么算_小强学Python+OpenCV之-1.4.4掩膜mask及位运算(与、或、非、异或)...
  10. PHP获取当前页面URL