Java安全多线程

时间:2020-03-20 10:17:18

标签: java multithreading

我对多线程有几个问题(我想安全,快速地完成我的小项目)。

我有一个图书馆。我将用户请求添加到文件中。

public static volatile HashMap<String, GooglePlayGame> games = new HashMap<>(500);

在每个应用程序启动时,我使用静态块中的文件(json + Jackson)初始化此哈希图:

static {
    TypeFactory typeFactory = mapper.getTypeFactory();
    MapType mapType = typeFactory.constructMapType(HashMap.class, String.class, GooglePlayGame.class);
      try {
          games = mapper.readValue(new File("games.json"), mapType);
        } catch (IOException e) {
            log.error(e.getMessage());
        }
    }

将处理每个用户的请求(使用特殊命令/ library),然后将新对“ key-value”添加到全局哈希图中,当然,如果key不存在(请使用containsKey进行检查)。然后使用此哈希图(而不是来自文件)。

然后我想将新的配对写入文件。为此,我想创建一个新线程,如下所示:

Thread thread = new Thread(() -> {
            try {
                mapper.writeValue(new File("games.json"), games);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        thread.start();

问题:

1)“易失性”有帮助吗? 是否可以保证在写入文件时始终能看到所有最后添加的对?

2)如果.. 写入文件不是每对新文件,而是每10对新文件?这该怎么做?使用CountDownLatch吗?如果是,如何正确组织呢?我不太擅长多语言阅读。 但是,如果程序崩溃并且我收到9个新请求,这些对将丢失!

3)顺便说一句,我是在这里创建一个新文件还是仅覆盖旧文件? 如果我总是创建新文件,这有点不好。杰克逊是创建新文件还是覆盖旧文件?

2 个答案:

答案 0 :(得分:1)

1)在这种情况下,volatile关键字无法满足您的期望。当搜索它的功能时,可能会有些误导。您会发现“ volatile关键字保证对所有变量的所有写入均对所有线程可见”。这意味着当您将新值(新对象)分配给变量时,它将可见。但是,如果更改分配给该变量的对象,则这些更改不一定对所有线程可见。

在您的情况下,您修改Hashmap而不是变量,因此它可能不可见。您应该考虑使用一些专用的线程安全的内置集合,例如ConcurrentHashMap

2)如果发生崩溃,您不能真正确保将所有数据都写入文件。在每次输入之后写入数据总是更安全,但这取决于它发生的频率。如果是每分钟一次,最好一次写入1,如果是每秒数千次,则应考虑进行批量写入。

3)我认为自己进行测试应该很容易。另外,它与关于多线程的主要问题并没有真正的关系。

答案 1 :(得分:1)

这是您使用volatile关键字的主要原因:

如果您有一些volatile ... x;,则在线程B观察到分配之后,线程A在分配x = v;之前所做的任何操作对线程B都是可见的。

final XType v = ...;
volatile XType x = ...some value other than v...;
AType a;
BType b;
CType c;

在线程A中:

a = ...;
b = ...;
x = v;
c = ...;

在线程B中:

while (x != v) {
    ...sleep, or spin, or maybe do some useful work...
}
...guaranteed to see the new values of a, and b here.
...No guarantee about c. Could see the old value or the new value.

但请注意!触发该行为的是分配 x = v;

您的程序初始化了volatile变量games,但是您的程序没有地方分配 games。程序中的任何内容都不会触发games的易失性。关键字在您的特定示例中无效。