同步块是否导致刷新所有写缓存?

时间:2019-06-17 21:35:55

标签: java multithreading synchronization jls

我对synchronized的工作方式(从本地缓存中清除写入的方式/时间)很感兴趣。假设我有以下代码:

class Scratch1 {
  int counter = 0;
  Scratch1() throws ExecutionException, InterruptedException {
    counter += 5;
    counter += 5;
    // Does this cause to flush possibly cached value written by main thread even if it locks
    // on totally unrelated object and the write doesnt happen inside the sync block?
    synchronized (String.class) {}
    Executors.newCachedThreadPool().submit(() -> {
      for (int i = 0; i < 1000; i++) {
        counter += 5;
      }
      synchronized (Integer.class) {}
    }).get();
    System.out.println(counter);
  }
}
class Scratch2 {
  int counter = 0;
  Scratch2() throws ExecutionException, InterruptedException {
    // Or is this only possible working way how flush written data.
    synchronized (String.class) {
      counter += 5;
      counter += 5;
    }
    Executors.newCachedThreadPool().submit(() -> {
      synchronized (Integer.class) {
        for (int i = 0; i < 1000; i++) {
          counter += 5;
        }
      }
    }).get();
    System.out.println(counter);
  }
}
class Scratch3 {
  volatile int counter = 0;
  Scratch3() throws ExecutionException, InterruptedException {
    counter += 5;
    counter += 5;
    Executors.newCachedThreadPool().submit(() -> {
      for (int i = 0; i < 1000; i++) {
        counter += 5;
      }
    }).get();
    System.out.println(counter);
  }
}

我有几个问题:

  1. 这三个示例是否共享相同的“线程安全性”级别(考虑到细节,例如第一次写入是由一个线程完成,而第二次写入是在第一个(是吗?)之后再由另一个线程完成),即“是保证打印5010”?
  2. 在同步块外部进行“操作”或使用非易失性属性(我希望易失性访问的速度为this post confirms)是否存在性能差异(至少是理论上的差异),但是在同步块的情况下仅当跨越同步的开始/结束时才支付的“冲洗”价格,或者在区块内时是否也存在差异?

1 个答案:

答案 0 :(得分:2)

  

我对同步如何在何时/何时从本地缓存中清除写入的意义感兴趣。

实际上,synchronized不会从本地缓存中清除写入。就像它这样做一样。

  

这三个示例是否共享相同的“线程安全性”级别(考虑到细节,例如第一次写入由一个线程完成,第二次写入在第一个(是吗?)之后并由另一个线程完成),即“是保证打印10张?”

它们都提供稍微不同形式的线程安全性。如果其他线程同时访问该对象,则它们都不是真正安全的。例如,另一个访问counter的线程将必须同时持有String.classInteger.class锁,以确保在操作过程中没有看到counter。尽管没有其他线程尝试修改counter是安全的,但是第三个方法使用的不是原子的增量操作。

  

在同步块外进行“操作”或使用非易失性属性是否存在性能差异(至少是理论上的差异)(如本文所证实,我希望易失性访问速度较慢),但在同步块的情况下,“仅在跨越同步的开始/结束时才支付“冲洗”价格,或者在区块内部时是否也有差异?

没有区别。输入synchronized块是有成本的,因为必须获取锁并且必须在整个入口点禁用某些优化。退出街区的费用相似。

在该块内没有任何费用,因为程序员提供了安全性,确保他们不允许任何线程修改该对象,除非该对象拥有相同的锁并且没有两个线程可以同时拥有相同的锁。一般来说,代码甚至可能不知道它是否在一个或多个synchronized块中,因为它可以深入到调用树中。