Java基础知识之synchronized同步方法、代码块、静态方法、静态代码块的区别

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

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

1.实例方法同步

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

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

2.静态方法同步

  静态方法的同步是指同步在该方法所在的类对象上。因为在Java虚拟机中一个类只能对应一个类对象,所以同时只允许一个线程执行同一个类中的静态同步方法。
  对于不同类中的静态同步方法,一个线程可以执行每个类中的静态同步方法而无需等待,一个类只能由一个线程同时执行。s示例代码:

public static synchronized void add(int value){
    count += value; // count位静态变量
 }

3.实例方法中的同步块

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

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

  示例使用Java同步块构造器来标记一块代码是同步的。该代码在执行时和同步方法一样。
  PS:注意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实例对象上,那么两个方法可以被线程同时执行。

4.静态方法中的同步块

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

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这个对象上。那么这两个方法可以同时被线程访问。

5.synchronized(this)、synchronized(object)、synchronized(*.class)区别

  下面单独对同步代码块的三种同步写法做一下区别:
(1)、synchronized(this)同步代码块:1)对其它的synchronized同步方法或synchronized(this)同步代码块调用是堵塞状态;2)同一时间只有一个线程执行同一对象的synchronized同步方法中的代码;
(2)、synchronized(object)进行同步操作时,对象监视器必须是同一个对象。不是同一个,运行就是异步执行了;
(3)、synchronized(*.class)代码块的作用其实和synchronized static方法作用一样。Class锁对类其作用,也就是对类所有对象实例起作用。

猜你喜欢

转载自blog.csdn.net/Alexlee1986/article/details/81219111
今日推荐