Java 具有多个线程的synchronizedList
我得到了下面的示例代码(使用Java),它将从多个线程访问Java 具有多个线程的synchronizedList,java,multithreading,Java,Multithreading,我得到了下面的示例代码(使用Java),它将从多个线程访问 public class ApplicationProducts { private final List<Product> myAppProducts = Collections.synchronizedList(new ArrayList<>()); private String firstPositionProductName; private int firstPosition
public class ApplicationProducts {
private final List<Product> myAppProducts = Collections.synchronizedList(new ArrayList<>());
private String firstPositionProductName;
private int firstPositionProductAvailability;
public void updateProducts(List<Product> products) {
myAppProducts.addAll(products);
}
public boolean checkAndReplaceFirstProduct(Product product) {
synchronized(myAppProducts) {
if((product.getId()).equals(myAppProducts.get(0).getId())) {
//calculations goes here to derive the below details
firstPositionProductAVailability = 10;
firstPositionProductName = abc;
return true;
} else {
return false;
}
}
}
public boolean removeFirstProduct(Product product) {
synchronized(myAppProducts) {
if((product.getId()).equals(myAppProducts.get(0).getId()) &(firstPositionProductName.getId().equals(myAppProducts.get(0).getId())) {
myAppProducts.remove(0);
return true;
} else {
throw new IllegalStateException(" Lock taken by some other product : product can't be removed ");
}
}
}
}
公共类应用程序产品{
私有最终列表myAppProducts=Collections.synchronizedList(新的ArrayList());
私有字符串firstPositionProductName;
私有int-firstproductavailability;
公共无效更新产品(列出产品){
myAppProducts.addAll(产品);
}
公共布尔checkAndReplaceFirstProduct(产品产品){
已同步(myAppProducts){
if((product.getId()).equals(myAppProducts.get(0.getId())){
//通过计算得出以下细节
firstPositionProductAVailability=10;
firstPositionProductName=abc;
返回true;
}否则{
返回false;
}
}
}
公共布尔removeFirstProduct(产品产品){
已同步(myAppProducts){
如果((product.getId()).equals(myAppProducts.get(0.getId())&(firstPositionProductName.getId().equals)(myAppProducts.get(0.getId())){
myAppProducts.remove(0);
返回true;
}否则{
抛出新的IllegalStateException(“被其他产品锁定:产品无法移除”);
}
}
}
}
我有以下问题,你能帮忙吗
(1) 上面的类是线程安全的吗
(2) 我真的需要对“myAppProducts”进行“同步”吗?因为我已经在检查某些条件,例如,从两个方法中删除“同步”后,该类是否是线程安全的?重要的一点是,在我的应用程序中,每个线程首先调用checkAndReplaceFirstProduct(),如果结果为真的话(表示获取了产品并进行了一些计算)然后只调用removeFirstProduct()
(3) 我是否也需要在updateProducts()中添加“同步”,这只是将更多的产品添加到现有列表中
(4) 我知道synchronizedList的迭代器应该是'synchronized'块的一部分(,它是否需要锁(同步)来访问'synchronizedList.get(index)'方法(如上所述)?是的,您需要
同步的块,但不是出于与myAppProducts
本身相关的任何原因:观察您对firstPositionProductAVailability
和firstPositionProductAVailability
的使用情况。现在,对这些成员的访问受到同步的块的保护。如果您如果移动这些块,您将为这些成员引入一个潜在的竞争条件
单独访问myAppProducts
不需要synchronized
块。包装器正确地联锁包装集合上的所有方法调用,但迭代除外(如文档中明确指出的)
通常,如果需要,您将需要同步的块
- 您打算通过
for
/迭代器
- 您需要实现一些操作,这些操作对于集合上的方法调用来说是非原子的(仅添加一个项,如果它不在列表中,等等),也就是说,如果集合上的单个逻辑“事务”必须使用包装器上的多个方法调用来实现
- 你有一些其他的状态需要保护(就像你的其他类成员的情况一样)
关于你的编辑
(2) 我真的需要对“myAppProducts”进行“同步”吗?因为我已经在检查某些条件,例如,在从两个方法中删除“同步”后,该类是否是线程安全的?一个重要的问题是,在我的应用程序中,每个线程都首先调用checkAndReplaceFirstProduct(),如果结果为真的话(表示获取产品并进行一些计算)然后只调用removeFirstProduct()
在这里,您有一个真正的竞争条件,如果不更改接口和/或通过这些方法的调用方的显式合作,您无法轻松解决这个问题。一个可能的解决方案是公开我们需要同步的对象,以便此类的客户机可以使用正确的方法:
public Object getSynchronizationObject() {
return myAppProducts;
}
以及你的客户必须做的文件
synchronized (obj.getSynchronizationObject()) {
if (obj.checkAndReplaceFirstProduct(something)) {
obj.removeFirstProduct(something);
}
}
我提到了这一点(但我不推荐!),因为这是Java的集合.synchronizedXxx
在迭代方面采取的方法。更好的解决方案是重新设计接口,但我对您的实际用例一无所知,所以我觉得很难在这里提出建议
上面的类是线程安全的吗
是的,看起来不错。但是我会在访问myAppProducts.get(0)
和myAppProducts.remove(0)
(如果列表为空怎么办?)
我真的需要“myAppProducts”上的“synchronization”吗?因为我已经在检查一些条件,例如,在从两个方法中删除“synchronized”之后,这个类是否是线程安全的
是的,根据您的代码设计:
- 对于原子性:这两种方法都有“check-then-act”语句-如果您删除同步,则当您测试时,
if
条件可能为true,但当您到达下一行时,该条件变为false
- 对于可见性:您将值分配给firstXxx变量,并且可以从不同的线程读取它们-如果不同步,读取的结果将是未定义的
我是否也需要在updateProducts()中添加“同步”,这只是将更多的产品添加到现有列表中
不同步任何addAll
我知道synchronizedList的迭代器应该是“synchronized”块的一部分。调用“synchronizedList.get(index)”时是否需要使用锁
不,您不需要,get
已同步。Th