【问题标题】:java synchronization from memory modeljava从内存模型同步
【发布时间】:2012-01-04 22:54:52
【问题描述】:

我读到JVM通过将共享变量的数据从主内存复制到线程的工作内存来实现同步。

enter link description here

例如,有这样一个类。

class Test {
private Test2 test2 = new Test2();

public void print1() {}

public synchronized void print2() {
    test2.print();
}

}

如果这个Test类在多个线程中执行,并且“print2”方法在一个线程中执行,我认为Test上的锁是由一个线程获得的,其他线程必须等到锁被释放。

现在我有一个问题。如果一个线程获得了对Test的锁,是否意味着Test和Test2的数据从主内存复制到了线程的工作内存?我说的原因是在实例方法级别使用了“同步”关键字,而 test2 是 Test 类的实例变量。

我只是想澄清从主内存复制到线程工作内存的内容。

如果我错了,请纠正我。

【问题讨论】:

    标签: java synchronization


    【解决方案1】:

    简而言之,当您使用同步时,所有共享变量都将被复制(即从缓存写入主内存,因此所有线程都具有相同的数据)。使用 volatile 时,只能保证复制一个 volatile 变量。

    我发现这是一个涉及主题的有用资源。

    http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html


    编辑:关于您的评论,specification 第 17.6 节回答了您的问题:

    令 T 为任意线程,令 V 为任意变量,令 L 为任意锁。 T 执行的动作有一定的限制 关于 V 和 L:

    在 T 对 L 的锁定操作和随后的使用或存储操作之间 通过对变量 V 的 T,必须干预对 V 的赋值或加载操作; 而且,如果是加载动作,那么对应的读取动作 如主内存所见,该负载必须遵循锁定操作。 (不太正式:锁定操作的作用就像它刷新所有变量一样 线程的工作内存;在使用之前,它们必须被分配或 从主内存加载。)

    【讨论】:

    • 如果我使用类似这样的同步块而不是在方法级别使用“同步”会发生什么?对象锁 = 新对象();同步(锁定) {test2.print();}
    • @user826323 我必须刷新我的记忆才能回答这个问题。请参阅我的更新答案。使用锁时,所有共享变量都会从主存中获取。
    【解决方案2】:

    仅当您至少有一个写入器和读取器线程时才需要同步。因为您没有修改任何不需要同步的内容。

    唯一被复制的是引用test2,它很可能被放置在一个寄存器中。无论您的方法是否同步,都会发生这种情况。

    【讨论】:

    • 我知道这个类没有修改任何东西。这只是一个例子。我只是想找出在 JVM 中进行同步时复制的内容。
    • 那么如果有另一个实例变量像String s = "test",那么这个's'也会被复制?
    • 好吧,实际上例子中有一个作家。 private Test2 test2 = new Test2();进行写操作。
    • @Yair,这是在构造函数中执行的,它将是单线程的。
    • @user826323, s 如果你使用它会被复制。同样,使用同步对普通读取没有影响。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-06
    • 1970-01-01
    • 2017-02-17
    • 1970-01-01
    • 2018-05-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多