gpt4 book ai didi

java - 在所有线程的同步块(synchronized block)中初始化静态变量,无需同步即可读取

转载 作者:行者123 更新时间:2023-12-01 07:44:04 24 4
gpt4 key购买 nike

我经常看到以下模式。一个线程将在同步块(synchronized block)的 init() 方法中初始化客户端。所有其他线程在开始使用其他类方法之前也调用 init() 方法。初始化后客户端值不会改变。他们不会将客户值(value)设置为不稳定的。

我的问题是这样做是否正确?在 init 方法完成后,所有创建客户端并调用 init() 方法的线程都会看到由调用 init() 方法的第一个线程初始化的正确初始化值吗?

public class DB {

private static Object lock = new Object();
private static Client client;

public init() {

synchronized (lock) {
if (client != null) {
return;
}
client = new Client();
}
}

public insert(Object data) {
client.insert(data); // is this ok to access the client without volatile or synchronized?
}
}

该模式背后的基本原理是,他们认为因为他们在 init() 方法中的同步块(synchronized block)下读取客户端,所以客户端将被设置为正确的初始化值,并且因为客户端从未更改,所以他们可以使用它之后没有 volatile 或同步。这个假设正确吗?

您可以在此处查看此模式:https://github.com/brianfrankcooper/YCSB/blob/cd1589ce6f5abf96e17aa8ab80c78a4348fdf29a/mongodb/src/main/java/site/ycsb/db/MongoDbClient.java他们在 init 方法中初始化数据库,然后在没有同步的情况下使用它。

最佳答案

只有保证在调用 insert(data) 之前调用 init() ,才可以安全地执行此操作。

synchronized block 创建了一个发生前边:同步块(synchronized block)的结束发生在下一次调用同一 block 之前。

这意味着如果线程调用了 init(),则:

  • client 之前未初始化,因此在此调用时对其进行了初始化。
  • client 之前已初始化,并且对 client 的写入是在当前线程进入 synchronized block 之前发生的。

那么就不需要进一步的同步,至少对于客户端来说是这样。

但是,如果线程调用init(),则无法保证client是否已初始化;并且不保证由另一个线程(调用了 init() 的线程)初始化的 client 是否对当前线程(未调用的线程)可见init())。

依赖客户端首先调用 init() 是很脆弱的。使用热切初始化的字段会更好:

public class DB {

private static final Client client = new Client();

public insert(Object data) {
client.insert(data); // Guaranteed to be initialized once class loading is complete.
}
}

或者,如果您必须惰性地执行此操作,请使用惰性支架:

public class DB {
private static class Holder {
private static final Client client = new Client();
}

public insert(Object data) {
Holder.client.insert(data); // Holder.client is initialized on first access.
}
}

或者,当然,在 insert 方法中插入对 init() 的调用:

  public insert(Object data) {
init();
client.insert(data);
}

后一种方法的缺点是所有线程都必须同步。在其他两种方法中,第一次调用后没有争用。

关于java - 在所有线程的同步块(synchronized block)中初始化静态变量,无需同步即可读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58238522/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com