【volatile-面试】内存屏障

Java中的volatile

 

Java也支持volatile关键字,但它被用于其他不同的用途。当volatile用于一个作用域时,Java保证如下:

  1. (适用于Java所有版本)读和写一个volatile变量有全局的排序。也就是说每个线程访问一个volatile作用域时会在继续执行之前读取它的当前值,而不是(可能)使用一个缓存的值。(但是并不保证经常读写volatile作用域时读和写的相对顺序,也就是说通常这并不是有用的线程构建)。
  2. (适用于Java5及其之后的版本)volatile的读和写建立了一个happens-before关系,类似于申请和释放一个互斥锁[1]。

使用volatile会比使用锁更快,但是在一些情况下它不能工作。volatile使用范围在Java5中得到了扩展,特别是双重检查锁定现在能够正确工作[2]。

如下:

Double-checked locking is actually OK as of Java 5 provided that you make the instance reference volatile. So for example, if we needed to pass in a database connection to getInstance(), then this would be OK:

public class MyFactory {
  private static volatile MyFactory instance;

  public static MyFactory getInstance(Connection conn)
       throws IOException {
    if (instance == null) {
      synchronized (MyFactory.class) {
        if (instance == null)
          instance = new MyFactory(conn);
      }
    }
    return instance;  
  }

  private MyFactory(Connection conn) throws IOException {
    // init factory using the database connection passed in
  }
}

Note that this is OK as of Java 5 because the definition of volatile was specifically changed to make it OK. Accessing a volatile variable has the semantics of synchronization as of Java 5. In other words Java 5 ensures that the unsycnrhonized volatile read must happen after the write has taken place, and the reading thread will see the correct values of all fields on MyFactory.

1  Section 17.4.4: Synchronization Order The Java Language Specification, 3rd Edition. Sun Microsystems. 2005 [2010-11-22].
 2 Neil Coffey. Double-checked Locking (DCL) and how to fix it. Javamex. [2009-09-19]
 

 

参考:

Double-checked Locking (DCL) and how to fix it (ctd)

https://www.javamex.com/tutorials/double_checked_locking_fixing.shtml

 

你可能感兴趣的:(java,面试)