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

Java同步关键字(synchronzied)

实例方法同步

静态方法同步

实例方法中同步块

静态方法中同步块

Java同步示例

Java 同步关键字(synchronized)

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

有四种不同的同步块:

实例方法

静态方法

实例方法中的同步块

静态方法中的同步块

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

实例方法同步

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

public synchronized void add(int value){

this.count += value;

}

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

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

静态方法同步

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

public static synchronized void add(int value){

count += value;

}

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

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

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

实例方法中的同步块

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

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

public void add(int value){

synchronized(this){

this.count += value;

}

}

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

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

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

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

public class MyClass {

public synchronized void log1(String msg1, String msg2){

log.writeln(msg1);

log.writeln(msg2);

}

public void log2(String msg1, String msg2){

synchronized(this){

log.writeln(msg1);

log.writeln(msg2);

}

}

}

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

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

静态方法中的同步块

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

public class MyClass {

public static synchronized void log1(String msg1, String msg2){

log.writeln(msg1);

log.writeln(msg2);

}

public static void log2(String msg1, String msg2){

synchronized(MyClass.class){

log.writeln(msg1);

log.writeln(msg2);

}

}

}

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

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

Java同步实例

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

public class Counter{

long count = 0;

public synchronized void add(long value){

this.count += value;

}

}

public class CounterThread extends Thread{

protected Counter counter = null;

public CounterThread(Counter counter){

this.counter = counter;

}

public void run() {

for(int i=0; i<10; i++){

counter.add(i);

}

}

}

public class Example {

public static void main(String[] args){

Counter counter = new Counter();

Thread threadA = new CounterThread(counter);

Thread threadB = new CounterThread(counter);

threadA.start();

threadB.start();

}

}

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

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

public class Example {

public static void main(String[] args){

Counter counterA = new Counter();

Counter counterB = new Counter();

Thread threadA = new CounterThread(counterA);

Thread threadB = new CounterThread(counterB);

threadA.start();

threadB.start();

}

}

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

java每一个小时同步_Java同步块(synchronized block)使用详解相关推荐

  1. java this关键字的使用_Java this 关键字的使用方法详解

    Java this 关键字的使用方法详解 构造方法中的this关键字 构造方法是一个类的对象在通过new关键字创建时自动调用的,在程序中不能向调用其他方法一样通过方法名(也就是类名)来调用.但如果一个 ...

  2. java原生类型没有封装_Java基本数据类型与封装类型详解(int和Integer区别)

    Java基本数据类型与封装类型详解(int和Integer区别) 发布于 2020-4-19| 复制链接 摘记: int是java提供的8种原始数据类型之一.Java为每个原始类型提供了封装类,Int ...

  3. java 封装表单数据类型_Java基本数据类型与封装类型详解(int和Integer区别)

    int是java提供的8种原始数据类型之一. Java为每个原始类型提供了封装类,Integer是java为int提供的封装类(即Integer是一个java对象,而int只是一个基本数据类型).in ...

  4. java中math的方法_Java中Math类常用方法代码详解

    近期用到四舍五入想到以前整理了一点,就顺便重新整理好经常见到的一些四舍五入,后续遇到常用也会直接在这篇文章更新... public class Demo{ public static void mai ...

  5. java case 多个值_Java switch多值匹配操作详解

    这篇文章主要介绍了Java switch多值匹配操作详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 我们都知道 switch 用来走流程分支,大 ...

  6. java中 enum什么意思_Java中枚举Enum的使用详解

    在某些情况下,一个类的对象时有限且固定的,如季节类,它只有春夏秋冬4个对象这种实例有限且固定的类,在 Java 中被称为枚举类: 在 Java 中使用 enum 关键字来定义枚举类,其地位与 clas ...

  7. java uml类图教程_Java利器之UML类图详解

    原标题:Java利器之UML类图详解 (点击上方公众号,可快速关注) 来源:伯乐在线专栏作者- Code4Android 如需转载,发送「转载」二字查看说明 前言 UML(Unified Modeli ...

  8. java 获取oracle表结构_Java导出oracle表结构实例详解

    Java导出oracle表结构实例详解 发布于 2020-7-20| 复制链接 摘记:  Java导出oracle表结构实例详解最近用到的,因为plsql是收费的,不让用,找了很多方法终于发现了这个. ...

  9. java数据结构排序实验报告_java数据结构与算法之插入排序详解

    本文实例讲述了java数据结构与算法之插入排序.分享给大家供大家参考,具体如下: 复习之余,就将数据结构中关于排序的这块知识点整理了一下,写下来是想与更多的人分享,最关键的是做一备份,为方便以后查阅. ...

  10. java启动监听器报错_JAVA通过JDBC连接Oracle数据库详解【转载】

    1.注册加载驱动 驱动名:DRIVER="oracle.jdbc.driver.OracleDriver"; Class.forName("驱动类名"); 2. ...

最新文章

  1. python回归模型 变量筛选_如何进行高维变量筛选和特征选择(一)?Lasso回归
  2. Hazelcast入门指南第6部分
  3. Windows 10环境下AndroidStudio安装教程(内含如何配置Http Proxy)
  4. LeetCode 674. 最长连续递增序列 (滑动窗口 计数法)
  5. CYQ.Data 正式支持 DotNET Core 版本发布
  6. Linux服务器时间设置命令
  7. 蓝桥杯2018国赛B组第四题 调手表
  8. 东京大学招生海报上的那些事(上)
  9. linux下运行testng,TestNG执行程序
  10. Pandas入门基本知识点
  11. 2019年最全的大数据学习大纲总结,持续更新.....
  12. 火狐浏览器翻译页面功能如何设置
  13. GPL协议允许你怎么卖?
  14. 用Imagex.exe 捕获Client机台映像并网络还原 网络还原篇
  15. 《猎杀U-571》影评
  16. 公众号微信内置地图在ios上不显示问题
  17. Premiere Pro之音乐衔接(五)
  18. 利用Java生成二维码
  19. (论文加源码)基于DEAP脑电数据集的脑电情绪识别(利用生成对抗性网络进行特征提取和数据扩充)
  20. 投票助力源码_公众号投票源码_女神来了投票5.2.0

热门文章

  1. wordpress的下载和安装介绍
  2. PHP之post请求php脚本实现
  3. C#实现中国天气网XML接口测试
  4. struts配置通配符*来匹配方法,实现动态调用
  5. Could not load the btn_020.disable.png image referenced from a nib in the bundle with identifier ...
  6. Flutter 微信分享功能实现
  7. java ArrayList 概述 与源码简析
  8. 使用vue来开发一个下拉菜单组件(2)
  9. 微信小程序之wx.request:fail错误,真机预览请求无效问题解决,安卓,ios网络预览异常(转)...
  10. 【Android】attr、style和theme