使用锁是否可以缓解由 volatile 关键字处理的问题?

问题描述 投票:0回答:0

我有一个

Foo
类,我认为它应该 not 是线程安全的,但我似乎无法重现这个问题。它具有的一种方法是
update
,它根据参数设置当前地图并改变旧地图。另一种方法是
read
,它总是从当前地图中获取值。

请查看测试示例。我有两个线程,一个调用

update
,另一个调用
read
。我希望
read
有时会从旧版本的
currMap
中读取(因为它不是
volatile
),它被
update
突变,因此返回
-1
,但它没有发生。这是巧合还是意料之中?

  private static class Foo {
    Map<Integer, Integer> currMap;
    Object lock = new Object();

    Foo(Map<Integer, Integer> newMap) {
      currMap = newMap;
    }

    void update(Map<Integer, Integer> newMap) {
      synchronized (lock) {
        Map<Integer, Integer> oldMap = currMap;
        currMap = newMap;
        oldMap.remove(0);
      }
    }

    int read() {
      int val;
      synchronized (lock) {
        val = currMap.getOrDefault(0, -1);
      }
      return val;
    }
  }
  @Test
  public void testExample() throws InterruptedException {
    AtomicInteger readWrong = new AtomicInteger(0);
    Map<Integer, Integer> map = new HashMap<>();
    map.put(0, 0);
    Foo foo = new Foo(new HashMap<>(map));
    Thread updater = new Thread(() -> {
      while (readWrong.get() == 0) {
        foo.update(new HashMap<>(map));
      }
    });

    Thread reader = new Thread(() -> {
      while (readWrong.get() == 0) {
        if (foo.read() == -1) {
          readWrong.incrementAndGet();
        }
      }
    });

    updater.start();
    reader.start();

    updater.join();
    reader.join();

    assertTrue(readWrong.get() > 0);
  }
java concurrency
© www.soinside.com 2019 - 2024. All rights reserved.