Java使用synchronized时我是否免费获得易失性功能?

Bev*_*vor 5 java concurrency multithreading volatile synchronized

我读了几篇关于并发性问题的帖子,但我仍然不确定某些事情.我可以说当使用synchronized时,我免费获得易失性功能,因为当释放对象的锁定时,下一个线程总是读取修改后的对象.对于volatile,对象的值会立即反映到其他线程.但是当我使用synchronized时,由于对象的锁定,不可能立即反映它.释放锁定后,只有另一个线程可以访问它.所以我不必关心立即将值反映到其他线程.我理解这个吗?

[更新]
示例打印总是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();
    }
}
Run Code Online (Sandbox Code Playgroud)

Erw*_*idt 2

不,根据 Java 内存模型,同步访问并不暗示易失性访问(尽管在特定实现上,可能是这样,但您不应该依赖于此)

\n\n

Java 语言规范 17.4.4(关于 Java 内存模型):

\n\n
\n

同步操作会引发操作上的同步关系,定义如下:

\n\n
    \n
  • 监视器 m 上的解锁操作与 m 上的所有后续锁定操作同步(其中“后续”是根据同步顺序定义的)。

  • \n
  • 对易失性变量 v (\xc2\xa78.3.1.4) 的写入与任何线程对 v 的所有\n 后续读取进行同步(其中“后续”是根据同步顺序定义的)。

  • \n
\n
\n\n

volatile对变量进行操作,并对synchronized对象的监视器(“锁”)进行操作。

\n\n

如果一个线程 A 刚刚退出对象O上的同步块,而另一个线程 B 刚刚读取对象O上的易失性变量(实例字段) V,则两个线程之间仍然存在同步关系。无法保证线程 A 会看到线程 B 所做的任何数据修改,反之亦然,直到线程 B 也在对象O上同步,或者直到线程 A 也访问对象O上的易失性字段V为止。

\n