原文:http://ifeve.com/synchronized-blocks/

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

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

Java 同步关键字(synchronized

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

有四种不同的同步块:

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

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

实例方法同步

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

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

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

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

静态方法同步

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

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

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

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

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

实例方法中的同步块

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

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

1 public void add(int value){
2  
3     synchronized(this){
4        this.count += value;
5     }
6   }

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

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

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

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

01 public class MyClass {
02  
03    public synchronized void log1(String msg1, String msg2){
04       log.writeln(msg1);
05       log.writeln(msg2);
06    }
07  
08    public void log2(String msg1, String msg2){
09       synchronized(this){
10          log.writeln(msg1);
11          log.writeln(msg2);
12       }
13    }
14  }

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

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

静态方法中的同步块

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

01 public class MyClass {
02     public static synchronized void log1(String msg1, String msg2){
03        log.writeln(msg1);
04        log.writeln(msg2);
05     }
06  
07     public static void log2(String msg1, String msg2){
08        synchronized(MyClass.class){
09           log.writeln(msg1);
10           log.writeln(msg2);
11        }
12     }
13   }

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

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

Java同步实例

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

01 public class Counter{
02      long count = 0;
03  
04      public synchronized void add(long value){
05        this.count += value;
06      }
07   }
08   public class CounterThread extends Thread{
09  
10      protected Counter counter = null;
11  
12      public CounterThread(Counter counter){
13         this.counter = counter;
14      }
15  
16      public void run() {
17     for(int i=0; i<10; i++){
18            counter.add(i);
19         }
20      }
21   }
22   public class Example {
23  
24     public static void main(String[] args){
25       Counter counter = new Counter();
26       Thread  threadA = new CounterThread(counter);
27       Thread  threadB = new CounterThread(counter);
28  
29       threadA.start();
30       threadB.start();
31     }
32   }

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

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

01 public class Example {
02  
03    public static void main(String[] args){
04      Counter counterA = new Counter();
05      Counter counterB = new Counter();
06      Thread  threadA = new CounterThread(counterA);
07      Thread  threadB = new CounterThread(counterB);
08  
09      threadA.start();
10      threadB.start();
11    }
12  }

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

Java同步块的更多相关文章

  1. Java同步块(synchronized block)使用详解

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

  2. 12、Java并发性和多线程-Java同步块

    以下内容转自http://ifeve.com/synchronized-blocks/: Java 同步块(synchronized block)用来标记方法或者代码块是同步的.Java同步块用来避免 ...

  3. java多线程-同步块

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

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

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

  5. Java并发编程(六)-- 同步块

    上一节已经讲到,使用Synchronzied代码块可以解决共享对象的竞争问题,其实还有其他的方法也可以避免资源竞争问题,我统称他们为Java同步块.Java 同步块(synchronized bloc ...

  6. synchronized同步块和volatile同步变量

    Java语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量.这两种机制的提出都是为了实现代码线程的安全性.其中 Volatile 变量的同步性较差(但有时它更简单并且开销更低),而 ...

  7. 转:Java同步synchronized使用

    原文链接 作者:Jakob Jenkov Java 同步块(synchronized block)用来标记方法或者代码块是同步的.Java同步块用来避免竞争.本文介绍以下内容: Java同步关键字(s ...

  8. Java 同步代码块 - Synchronized Blocks

    java锁实现原理: http://blog.csdn.net/endlu/article/details/51249156 The synchronized keyword can be used ...

  9. [转]关于java中的 sychronized 同步方法 与 同步块的理解

    首先,需要说明一点,也是最重要的一点,无论是同步方法 还是 同步块 都是只针对同一个对象的多线程而言的,只有同一个对象产生的多线程,才会考虑到 同步方法 或者是 同步块,如果定义多个实例的同步,可以考 ...

随机推荐

  1. Unity3d 适配机型

    1,为了是更多机型能够安装你的游戏,Unity3d Device Filter设置:ARMv6 with VFP: 2,华为C8600,一运行强制停止: 参考网址:http://forum.unity ...

  2. Linux文件普通权限

    1.文件所有者,所属用户组,其他用户1)文件所有者:创建文件的用户2)所属用户组:文件属于哪个用户组3)其他用户:不是文件所有者,不属于文件所属用户组的用户,称为其他用户 2.Linux文件权限我们切 ...

  3. 015. asp.net实现简易聊天室

    通过Application和Session来实现简单的聊天室和在线用户数统计 Global.asax代码: <%@ Application Language="C#" %&g ...

  4. linux终端-console

    echo $TERM 在ssh上是xterm 在console上是linux setterm -foreground black -background white -store http://blo ...

  5. 简单了解ddos攻击

    1.一种为流量攻击,主要是针对网络带宽的攻击,即大量攻击包导致网络带宽被阻塞,合法网络包被虚假的攻击包淹没而无法到达主机: 2.另一种为资源耗尽攻击,主要是针对服务器主机的攻击,即通过大量攻击包导致主 ...

  6. Redis Cluster 在PHP上的实践

    版本:redis3.0.3 redis——slot: 'master' => [ '192.168.1.55:7000'=>[0,5460], '192.168.1.55:7001'=&g ...

  7. linux Shell的使用

    linux Shell的使用 下面是我对shell脚本使用的学习,写成日志,做个笔记,可以当做自己以后的复习. 1.输出hello world! vi test1.sh, 如果不会vi工具的使用,请参 ...

  8. 配置Windows Server2008+iis+php+mysql所需下载安装包

    最近一个朋友让我帮忙给配置服务器iis+php+mysq 环境,遇到了很多问题,特此就在这里说一下.小弟只是在windwos2003 和windwos XP下配置过iis+php+mysql,去朋友那 ...

  9. 转载:mybatis自动生成

    MyBatis Generator中文文档 MyBatis Generator中文文档地址: http://generator.sturgeon.mopaas.com/ 该中文文档由于尽可能和原文内容 ...

  10. SPOJ #2 Prime Generator

    My first idea was Sieve of Eratosthenes, too. But obviously my coding was not optimal and it exceede ...