我有以下示例代码(使用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)'方法(如上所述) )?
答案 0 :(得分:2)
是的,您需要synchronized
个屏蔽,但不是因为与myAppProducts
本身相关的任何原因:请注意您对firstPositionProductAVailability
和firstPositionProductAvailability
的使用情况。就像现在一样,访问这些成员受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'后,这个类是否是线程安全的?
是的,你是根据你的代码设计做的:
if
条件在测试时可能为真,但在到达下一行时变为false / LI>
我是否还需要在updateProducts()中添加“同步”,这只是将更多产品附加到现有列表中?
没有同步addAll
。
我知道synchronizedList的Iterator应该是'synchronized'块的一部分。调用'synchronizedList.get(index)'时是否需要使用锁?
不,不,get
已经同步。