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

  • Java 同步关键字(synchronzied)
  • 实例方法同步
  • 静态方法同步
  • 实例方法中同步块
  • 静态方法中同步块
  • Java 同步示例

Java 同步关键字(synchronized)

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

有四种不同的同步块:

  1. 实例方法
  2. 静态方法
  3. 实例方法中的同步块
  4. 静态方法中的同步块

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

实例方法同步

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

 public synchronized void add(int value){
this.count += value;
}

静态方法同步

静态方法同步和实例方法同步方法一样,也使用 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多线程-同步块的更多相关文章

  1. java多线程——同步块synchronized详解

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

  2. 转:关于JAVA多线程同步

    转:http://lanvis.blog.163.com/blog/static/26982162009798422547/ 因为需要,最近关注了一下JAVA多线程同步问题.JAVA多线程同步主要依赖 ...

  3. Java多线程-同步:synchronized 和线程通信:生产者消费者模式

    大家伙周末愉快,小乐又来给大家献上技术大餐.上次是说到了Java多线程的创建和状态|乐字节,接下来,我们再来接着说Java多线程-同步:synchronized 和线程通信:生产者消费者模式. 一.同 ...

  4. Java多线程同步问题的探究

    一.线程的先来后到——问题的提出:为什么要有多线程同步?Java多线程同步的机制是什么? http://www.blogjava.net/zhangwei217245/archive/2010/03/ ...

  5. java多线程同步

    一篇好文:java多线程机制同步原则 概括起来说,Java 多线程同步机制主要包含如下几点:1:如果一个类包含一个或几个同步方法,那么由此类生成的每一个对象都配备一个队列用来容纳那些等待执行同步的线程 ...

  6. 浅谈Java多线程同步机制之同步块(方法)——synchronized

    在多线程访问的时候,同一时刻只能有一个线程能够用 synchronized 修饰的方法或者代码块,解决了资源共享.下面代码示意三个窗口购5张火车票: package com.jikexueyuan.t ...

  7. Java多线程同步机制之同步块(方法)——synchronized

    在多线程访问的时候,同一时刻只能有一个线程能够用 synchronized 修饰的方法或者代码块,解决了资源共享.下面代码示意三个窗口购5张火车票: package com.jikexueyuan.t ...

  8. Java多线程同步 synchronized 关键字的使用

    代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D)运行完这个方法后再运行此线程A, ...

  9. Java多线程---同步与锁

    一,线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏. 二.同步和锁定 1.锁的原理 Java中每个对象都有一个内置锁. 当程序运行到非静态的synchronized同步方法上时,自动 ...

随机推荐

  1. QQ表情动图,增加写博客的乐趣

    QQ表情动图,增加写博客的乐趣 body{margin:0px;}

  2. Ubuntu14中supervisor的安装及配置

    supervisor是一款很好用的进程管理工具,其命令也很简单,其安装过程如下: Ubuntu14: 首先保证本地的Python环境是OK的,并且已经安装supervisor包,如果没有安装可以用ea ...

  3. PNG使用技巧 PNG的使用技巧

    PNG的格式和透明度 这个Fireworks会比较清楚,打开Fireworkd优化面板,可以清楚看到png有3种不同深度的格式:png8.png24.png32. 其中,在优化面板选择png8,可发现 ...

  4. Python——functools

    该模块为高阶函数提供支持——作用于或返回函数的函数被称为高阶函数.在该模块看来,一切可调用的对象均可视为本模块中所说的“函数”. 目录 一.模块方法 1. functools.cmp_to_key(f ...

  5. MIME参考列表

    定义 MIME(multipurpose internet mail extensions)多用途互联网邮件扩展类型是描述消息内容类型的因特网标准.MIME消息能包含文本.图像.音频.视频以及其他应用 ...

  6. JSP网站开发基础总结《十一》

    继上一篇关于过滤器连总结后,本篇为大家详细介绍一下过滤器中过滤规则的dispatcher属性的使用,在servlet2.5中dispatcher的属性有四种,其中上一篇已经为大家介绍了error属性的 ...

  7. java中finally和return的执行顺序

    注意:return的位置... 从这几个例子中可以看到,如果try之前没有有条件的return,则try..catch..finally语句块中的语句都是顺序执行(如果try中或者catch中 有re ...

  8. Oracle工具之DBNEWID

    DBNEWID是Oracle提供的一个用于修改数据库DBID和DBNAME的工具. 在引进该工具之前,如果我们想修改数据库的数据库名,必须重建控制文件.但即便如此,也无法修改该数据库的DBID.众所周 ...

  9. art-template用户注册方法

    应用场景nodejs Express框架,使用art-template模板引擎. 后台注册方法代码: var template = require('art-template'); template. ...

  10. 浅谈servlet版本

    说白话,eclipseJ2EE版本新建一个web项目后,在IDE中的项目根目录下会看到2.3,2.4,2.5,3.0,3.1....据说最新的4.0在路上,已经有草案了,很期待ing. 360百科是这 ...