8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

同步 getter 方法是否看到完全或部分初始化的对象?

Luis Bauer 1月前

30 0

假设我有下一个类:class Point { int x, y, z; public Point(int x, int y, int z) { this.x = x; this.y = y; this.z = z; } public **synchroni...

假设我有下一堂课:

class Point {

    int x, y, z;

    public Point(int x, int y, int z) {
        this.x = x; 
        this.y = y; 
        this.z = z;  
    }

    public **synchronized** int getSum() {
        return x + y + z;
    }
}

如果我要共享对多个线程的引用,是否可以在 同步的 getSum() 方法中拥有部分初始化的字段?

Point p = new Point(1,2,3);
int sum = p.getSum();

是否有可能得到如下结果:

sum = 0 (OK);
sum = 6 (OK);
sum = 1 (x = 1, y = 0, z = 0) (INTERESTING);
sum = 2 (x = 0, y = 2, z = 0) (INTERESTING);
sum = 3 (x = 0, y = 0, z = 3) (INTERESTING);
sum = 5 (x = 1, y = 2, z = 3) (INTERESTING);
and so on..

这里确实存在先发生保证吗?如果一个线程获得 Point 的锁并进入同步方法,是否意味着调用构造函数的线程已经完成了所有初始化?

对我来说,显然有可能得到以下结果:

sum = 0 (OK);
sum = 6 (OK);

那么下一个不变量呢?有可能吗?

sum = 1 (x = 1, y = 0, z = 0) (INTERESTING);
sum = 2 (x = 0, y = 2, z = 0) (INTERESTING);
sum = 3 (x = 0, y = 0, z = 3) (INTERESTING);
sum = 5 (x = 1, y = 2, z = 3) (INTERESTING);

我认为 Point 对象的引用在多个线程之间共享,没有适当的同步或安全发布,因此无法保证其他线程将看到完全构造的对象。这意味着如果对象未安全发布,线程可能会观察到部分初始化的字段。同步方法不能保证对象本身的安全发布。如果对象未安全发布,另一个线程可能会观察到部分构造的 Point 对象,即使在调用同步的 getSum() 方法时也是如此。

因此,没有先发生保证...你同意我的观点吗?


有一个有趣的答案 在构造函数中进行同步以使其先发生 。但我不同意:

任何同步方法(或块)都保证能看到构造函数的全部效果,或者看不到任何效果;它不会只看到构造函数的一部分

我说得对吗?

帖子版权声明 1、本帖标题:同步 getter 方法是否看到完全或部分初始化的对象?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Luis Bauer在本站《multithreading》版块原创发布, 转载请注明出处!
最新回复 (0)
  • @MarkRotteveel 感谢您的评论!但是重新排序怎么办?第一个操作是初始化 x 字段,然后第二个操作是将引用分配给 p?

返回
作者最近主题: