如果不使用同步,可能一直读不到数据,或是读取没有写过的数据(失效值)。
# 细节和JVM优化、体系结构相关。同步提供了规范来避免这些问题。
理了一些书中的例子,写成了Demo,方便有直观感受,可以看看 ;)
github java-concurrency http://t.cn/RvCvlhc
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2013-07-21
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操作还会引起数据失效? 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2013-07-21
个人认为只需要把把set操作设置为synchronized,get操作不需要加锁同步
|
|
返回顶楼 | |
发表时间:2013-07-22
最后修改:2013-07-22
set 操作虽然是同步的 但不是原子的。 比如 get发生在set操作结束之前, 那你拿到的value值 不是最新的。
|
|
返回顶楼 | |
发表时间:2014-06-20
最后修改:2014-06-20
如果不使用同步,可能一直读不到数据,或是读取没有写过的数据(失效值)。 # 细节和JVM优化、体系结构相关。同步提供了规范来避免这些问题。
理了一些书中的例子,写成了Demo,方便有直观感受,可以看看 ;) github java-concurrency http://t.cn/RvCvlhc |
|
返回顶楼 | |