[英]Java When using synchronized do I get volatile functionality for free?
我读了几篇关于并发性问题的帖子,但我仍然不确定某些事情。 我可以说当使用synchronized时,我免费获得易失性功能,因为当释放对象的锁定时,下一个线程总是读取修改后的对象。 对于volatile,对象的值会立即反映到其他线程。 但是当我使用synchronized时,由于对象的锁定,不可能立即反映它。 释放锁定后,只有另一个线程可以访问它。 所以我不必关心立即将值反映到其他线程。 我理解这个吗?
[UPDATE]
示例打印总是1 2 3 4 5 6 7 8 9没有易失性。
package main;
public class Counter
{
public static long count = 0;
}
public class UseCounter implements Runnable
{
public void increment()
{
synchronized (this)
{
Counter.count++;
System.out.print(Counter.count + " ");
}
}
@Override
public void run()
{
increment();
increment();
increment();
}
}
public class DataRace
{
public static void main(String args[])
{
UseCounter c = new UseCounter();
Thread t1 = new Thread(c);
Thread t2 = new Thread(c);
Thread t3 = new Thread(c);
t1.start();
t2.start();
t3.start();
}
}
不,根据Java内存模型,同步访问并不暗示易失性访问(尽管在特定实现中,它可能是,但您不应该依赖于此)
同步动作引发与动作的同步关系,定义如下:
监视器m上的解锁动作与m上的所有后续锁定动作同步(其中“后续”根据同步顺序定义)。
对易失性变量v(第8.3.1.4节)的写入与任何线程对v的所有后续读取同步(其中“后续”根据同步顺序定义)。
volatile
对变量进行操作,并在对象的监视器(“锁定”)上进行synchronized
操作。
如果一个线程A刚刚退出对象O上的同步块,而另一个线程B刚刚读取了对象O上的volatile变量(实例字段) V ,则两个线程之间仍然没有同步关系。 无法保证线程A将看到线程B完成的任何数据修改,反之亦然,直到线程B也在对象O上同步,或者直到线程A也访问对象O上的易失性字段V.
拥有volatile变量与同步访问不同。 将变量标记为volatile时,访问该对象的Thread
对象将不会保留本地缓存,并且只会有一个“副本”。 如果你将两者(synchronized和volatile)结合起来,那么它将始终是更新版本,并且你不会有相互冲突的访问权限。
您的代码保证打印1 2 3 4 5 6 7 8 9.原因是如果您有一个序列,如
然后保证步骤4的读取在步骤1看到写入。
这与volatile
因为不能保证写入立即反映回存储器,而是仅保证步骤1中的写入在步骤3结束时对t2可见。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.