synchronizedList与多个线程

时间:2016-10-03 11:05:00

标签: java multithreading

我有以下示例代码(使用Java),它将从多个线程访问。

$scope.getCountries = function () {
    new countriesService
            .countries
            .query({ }, getCountriesSuccess, getCountriesError);
};

我有以下问题,你能帮忙吗?

(1)上面的类线程是否安全?

(2)我真的需要'myAppProducts'上的'同步',因为我已经检查了一些条件,即从两种方法中删除'synchronized'后这个类是否是线程安全的? 重要的一点是,在我的应用程序中,每个线程首先调用checkAndReplaceFirstProduct(),如果结果为true(表示获取产品并进行一些计算),然后只调用removeFirstProduct()

(3)我是否还需要在updateProducts()中添加“同步”,这只是将更多产品附加到现有列表中?

(4)我知道synchronizedList的Iterator应该是'synchronized'块(https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#synchronizedList(java.util.List)的一部分,它是否需要锁(同步)来访问'synchronizedList.get(index)'方法(如上所述) )?

2 个答案:

答案 0 :(得分:2)

是的,您需要synchronized个屏蔽,但不是因为与myAppProducts本身相关的任何原因:请注意您对firstPositionProductAVailabilityfirstPositionProductAvailability的使用情况。就像现在一样,访问这些成员受synchronized块的保护。如果删除这些块,则会引入与这些成员相关的潜在竞争条件!

仅访问myAppProducts不需要synchronized个阻止。包装集合上的所有方法调用都由包装器正确地互锁,但迭代的显着例外(如文档中明确指出的那样)。

通常,如果

,您将需要synchronized
  • 您打算通过for / iterator
  • 对代码进行迭代
  • 你需要实现一些动作,这对于集合上的方法调用是非原子的(仅添加项目,如果它不在列表中,等等),即,如果是单个逻辑“事务” “必须使用包装器上的多个方法调用来实现集合
  • 你还有其他一些要保护的州(就像你和其他班级成员一样)

关于您的编辑

  

(2)我真的需要'myAppProducts'上的'同步',因为我已经检查了一些条件,即从两种方法中删除'synchronized'后这个类是否是线程安全的?重要的一点是,在我的应用程序中,每个线程首先调用checkAndReplaceFirstProduct(),如果结果为true(表示获取产品并进行一些计算),然后只调用removeFirstProduct()?

在这里,你有一个真正的竞争条件,如果不改变界面和/或这些方法的调用者的明确合作,你就无法轻易解决。一个可能的解决方案是公开我们需要同步的对象,以便这个类的客户端可以做正确的事情:

public Object getSynchronizationObject() {
    return myAppProducts;
}

并记录,您的客户必须

synchronized (obj.getSynchronizationObject()) {
    if (obj.checkAndReplaceFirstProduct(something)) {
        obj.removeFirstProduct(something);
    }
}

我提到了这个(但我不推荐它!),因为这是Java Collections.synchronizedXxx关于迭代的方法。一个更好的解决方案是重新设计界面,但我对你的实际用例一无所知,所以我觉得很难在这里提出一个提案。

答案 1 :(得分:2)

  

上面的类线程是否安全?

是的看起来不错。但是我会在访问myAppProducts.get(0)myAppProducts.remove(0)之前添加一些检查(如果列表为空,该怎么办?)。

  

我真的需要'myAppProducts'上的'同步',因为我已经检查了一些条件,即,从两种方法中删除'synchronized'后,这个类是否是线程安全的?

是的,你是根据你的代码设计做的:

  • for atomicity:两种方法都有“check-then-act”语句 - 如果删除同步,if条件在测试时可能为真,但在到达下一行时变为false / LI>
  • 用于可见性:您可以为firstXxx变量赋值,并可以从不同的线程读取它们 - 如果没有同步,则读取的结果是未定义的。
  

我是否还需要在updateProducts()中添加“同步”,这只是将更多产品附加到现有列表中?

没有同步addAll

  

我知道synchronizedList的Iterator应该是'synchronized'块的一部分。调用'synchronizedList.get(index)'时是否需要使用锁?

不,不,get已经同步。