Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 具有多个线程的synchronizedList_Java_Multithreading - Fatal编程技术网

Java 具有多个线程的synchronizedList

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

我得到了下面的示例代码(使用Java),它将从多个线程访问

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