此同步代码是否导致不必要的线程等待?

时间:2014-10-21 15:30:01

标签: java multithreading

我们有一个应用程序,它有一个类,用于保存通过数据库填充的成员。以下是这种情况的代表性例子。

private AtomicBoolean data1Initialized = new AtomicBoolean(false);
protected SomeSynchronizedDataStructure<Object> data1 = <initializeit>;

protected final synchronized void initData1() {
    if (data1Initialized.compareAndSet(false, true)){
        // Populate data1 data structure from database
    }
}
public SomeSynchronizedDataStructure<Object> getData1(){
    initData1();
    return data1;
}

我们对data1,data2,data3 ... dataN有相同的模式。每个dataStructure都与另一个没有关系,它们只是在同一个类中。跨多个线程访问此数据。关于这种模式的一些问题:

同步这些方法会使线程必须等待所有不同dataN的布尔检查,对吗?哪个是不必要的?

数据结构是否需要同步?数据在整个应用程序生命周期内不会发生变化。我认为只有初始化它才需要同步,访问可能会发生不同步。

对我个人最重要

这会导致死锁吗?我想不,但我对线程没有经验。

2 个答案:

答案 0 :(得分:3)

当您在课堂创作时初始化时,您只需要:

public class DataHolder {
    // Note: 'final' is needed to ensure value is committed to memory before DataHolder
    private final SomeSynchronizedDataStructure<Object> data1 = <initializeit>;

    public SomeSynchronizedDataStructure<Object> getData1(){
        return data1;
    }
}

因为“initializeit”代码将在类的构造函数中运行,所以当你有一个可以传递的类句柄时,它就会准备就绪。 E.g:

DataHolder dataHolder = new DataHolder();
// dataHolder has already created the data structure by the time I do...
dataHolder.getData1();

如果您确实想要使用延迟加载,只需使用synchronized:

public class DataHolder {
    private SomeSynchronizedDataStructure<Object> data1;

    public synchronized SomeSynchronizedDataStructure<Object> getData1() {
        // synchronized guarantees each thread will see "data1" just as the
        // last thread left it.
        if(data1 == null) {
            data1 = initializeit();
        }
        return data1;
    }
}

答案 1 :(得分:1)

  

同步这些方法会使线程必须等待所有不同数据N的布尔检查,对吗?

正确。

  

哪个不必要?

是的,这是不必要的,因为数据N是不相关的。

  

数据结构是否需要同步?数据在整个应用程序生命周期内不会发生变化。我认为只有初始化它才需要同步,访问可能会发生不同步。

再次,正确。 BarrySW19的答案为您提供了安全初始化而无需同步的模式。

  

对我个人最重要

     

这会导致死锁吗?我想不,但我没有线程经验。

它本身不会导致死锁。但是,如果其中一个数据init方法调用在另一个监视器上同步的其他东西(称之为m),同时其他一些线程拥有m并且现在尝试初始化其中一个dataNs,那就是死锁。