synchronized的锁对象的特点

来源:互联网 发布:手机免root数据恢复apk 编辑:程序博客网 时间:2024/06/10 15:27

JAVA中synchronized关键字能够作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。假如再细的分类,synchronized可作用于instance变量、object reference(对象引用)、static函数和class literals(类名称字面常量)身上。synchronizedvoidf() { /* body */ }void f() { synchronized(this) { /* body */} }完全等价的。

synchronized(class)很特别,它会让另一个线程在任何需要获取class做为monitor的地方等待。class与this作为不同的监视器可以同时使用,不存在一个线程获取了class,另一个线程就不能获取该class的一切实例。

  1. 对于实例同步方法,锁是当前实例对象。
  2. 对于静态同步方法,锁是当前对象的Class对象。
  3. 对于同步方法块,锁是Synchonized括号里配置的对象。
class与this的几种情况:
synchronized(class)
synchronized(this)

线程各自获取monitor,不会有等待。

synchronized(this)
synchronized(this)

如果不同线程监视同一个实例对象,就会等待;如果不同的实例,不会等待。

synchronized(class)
synchronized(class)

如果不同线程监视同一个实例或者不同的实例对象,都会等待。



单例模式,有“懒汉式”和“饿汉式”两种。

懒汉式

单例类的实例在第一次被引用时候才被初始化。

public class Singleton {      private static Singleton instance=null;           private Singleton() {               }           public static Singleton getInstance(){          if (instance == null) {              instance = new Singleton();          }                   return instance;      }  }

饿汉式

单例类的实例在加载的时候就被初始化。

public class Singleton {      private static Singleton instance = new Singleton();           private Singleton() {               }           public static Singleton getInstance(){          return instance;      }  }

在单线程程序中,上面两种形式基本可以满足要求了,但是在多线程环境下,单例类就有可能会失效,这个时候就要对其加锁了,来确保线程安全。

对线程加锁用的synchronized关键字,这个关键字的用法主要也分为两种:

一种是加在方法名之前,形如:synchronized methodeName(params){……};

二是声明同步块,形如:synchronized(this){……};

下面是对懒汉式单例类加上线程同步的实现:

同步方法:

public class Singleton {      private static Singleton instance=null;           private Singleton() {               }           public synchronized static Singleton getInstance(){          if (instance == null) {              instance = new Singleton();          }                   return instance;      }  }

这种方式效率比较低,性能不是太好,不过也可以用,因为是对整个方法加上了线程同步,其实只要在new的时候考虑线程同步就行了,这种方法不推荐使用。

同步代码块:

public class Singleton {      private static Singleton instance;      private final static Object syncLock = new Object();           private Singleton() {               }           public static Singleton getInstance(){          if (instance == null) {              synchronized (syncLock) {                  if (instance == null) {                      instance = new Singleton();                  }              }          }                   return instance;      }  }

synchronized同步块括号中的锁定对象是采用的一个无关的Object类实例,而不是采用this,因为getInstance是一个静态方法,在它内部不能使用未静态的或者未实例的类对象,因此也可以用下面的方法来实现:

public class Singleton {      private static Singleton instance;           private Singleton() {               }           public static Singleton getInstance(){          if (instance == null) {              synchronized (Singleton.class) {                  if (instance == null) {                      instance = new Singleton();                  }              }          }                   return instance;      }  }

同步代码块的这两种方式都是比较推荐使用的,我就一直在项目中使用,有问题以后可以再改进。


原创粉丝点击