论坛首页 Java企业应用论坛

Java Concurrency In Practice 失效数据讨论

浏览 2416 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2013-07-21  
章节内容 http://book.51cto.com/art/201203/323212.htm


3.1.1 失效数据

NoVisibility展示了在缺乏同步的程序中可能产生错误结果的一种情况:失效数据。当读线程查看ready变量时,可能会得到一个已经失效的值。除非在每次访问变量时都使用同步,否则很可能获得该变量的一个失效值。更糟糕的是,失效值可能不会同时出现:一个线程可能获得某个变量的最新值,而获得另一个变量的失效值。

通常,当食物过期(即失效)时,还是可以食用的,只不过味道差了一些。但失效的数据可能导致更危险的情况。虽然在Web应用程序中失效的命中计数器可能不会导致太糟糕的情况,但在其他情况中,失效值可能会导致一些严重的安全问题或者活跃性问题。在NoVisibility中,失效数据可能导致输出错误的值,或者使程序无法结束。如果对象的引用(例如链表中的指针)失效,那么情况会更复杂。失效数据还可能导致一些令人困惑的故障,例如意料之外的异常、被破坏的数据结构、不精确的计算以及无限循环等。

程序清单3-2中的Mutablelnteger不是线程安全的,因为get和set都是在没有同步的情况下访问value的。与其他问题相比,失效值问题更容易出现:如果某个线程调用了set,那么另一个正在调用get的线程可能会看到更新后的value值,也可能看不到。

程序清单 3-2 非线程安全的可变整数类

@NotThreadSafe 
public class MutableInteger { 
   private int value; 

   public int  get() { return value; } 
   public void set(int value) { this.value = value; } 
}
在程序清单3-3的SynchronizedInteger中,通过对get和set等方法进行同步,可以使MutableInteger成为一个线程安全的类。仅对set方法进行同步是不够的,调用get的线程仍然会看见失效值。

程序清单 3-3 线程安全的可变整数类

@ThreadSafe 
public class SynchronizedInteger { 
   @GuardedBy("this") private int value; 

   public synchronized int get() { return value; } 
   public synchronized void set(int value) { this.value = value; } 
}



既然做了set同步,数据的设置操作已经是原子的了,为什么get操作还会引起数据失效?
   发表时间:2013-07-21  
个人认为只需要把把set操作设置为synchronized,get操作不需要加锁同步
0 请登录后投票
   发表时间:2013-07-22   最后修改:2013-07-22
set 操作虽然是同步的 但不是原子的。 比如 get发生在set操作结束之前, 那你拿到的value值 不是最新的。
0 请登录后投票
   发表时间:2014-06-20   最后修改:2014-06-20

如果不使用同步,可能一直读不到数据,或是读取没有写过的数据(失效值)。

# 细节和JVM优化、体系结构相关。同步提供了规范来避免这些问题。

 

理了一些书中的例子,写成了Demo,方便有直观感受,可以看看 ;)

github java-concurrency http://t.cn/RvCvlhc

0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics