编程程序员

《七天七并发》笔记第一天互斥和内存模型

2016-03-18  本文已影响258人  铁眉

《七天七并发》第一天互斥和内存模型

java内存模型

《The Java Memory Model》http://www.cs.umd.edu/~pugh/java/memoryModel/

界定了这些并发问题的界限,并给出解决方案。

final

int old memory model. synchronization was the only way to ensure that all threads see the value of a final field that was written by the constructor.
新的JMM中,只要constructor过程中this不逸出,则能保证final字段被其他线程正确的看到,如果final字段指向一个数组或对象,数组或对象,也能保证其他线程看到构造器结束那个点的最新的值,而不是现在最新的值(因为构造完成后,有可能先被其他线程更新了)。

volatile

Under the old memory model, accesses to volatile variables could not be reordered with each other, but they could be reordered with nonvolatile variable accesses. 这样会导致volatile不能作为两个线程之间的信号变量,因为线程B看到volatile的变量变更后,不能保证在线程A中排在该volatile变量之前的write能被看到。
于是volatile变量似乎有了锁的作用:Writing to a volatile field has the same memory effect as a monitor release, and reading from a volatile field has the same memory effect as a monitor acquire.
In effect, because the new memory model places stricter constraints on reordering of volatile field accesses with other field accesses, volatile or not, anything that was visible to thread A when it writes to volatile field f becomes visible to thread B when it reads f.
因此volatile只能保证可见性问题,没法保证互斥问题。

volatile很实用于开关场景,比如标识一件事做完了,比如初始化完成了,或者网络请求处理完成。

"double-checked locking" problem

为了lazy init,某个field被使用时候才init。

class SomeClass {
  private Resource resource = null;
  public Resource getResource() {
    if (resource == null) {
      synchronized {
        if (resource == null) 
          resource = new Resource();
      }
    }
    return resource;
  }
}

因为可能在Resource构造完成之前,它的引用就被赋给SomeClass的field resource。所以线程B可能看到被初始化了一般的Resource对象。
The class loader, which synchronizes on the classes' Class object, executes static initializer blocks at class initialization time. That means that the effect of static initializers is automatically visible to all threads as soon as the class loads.

【解决方案一】:
static filed的初始化已经基于这个class的class obj synchronizes过了,所以一旦初始化完成能理解被其他thread看到:
The class loader, which synchronizes on the classes' Class object, executes static initializer blocks at class initialization time. That means that the effect of static initializers is automatically visible to all threads as soon as the class loads.
基于这个,另外为了保证lazy load,可以这么做:
When the initialized object is a static field of a class with no other methods or fields, the JVM effectively performs lazy initialization automatically.

【解决方案二】:在JSR133标准实施后(>= jdk1.5),可以通过将resource申明为violate解决这个问题。

上一篇 下一篇

猜你喜欢

热点阅读