以下方法是否是线程安全的?

3

我想知道以下方法是否是线程安全的。

用例:我从不同的位置传递两个集合...

public static Collection<String> checkIfValidUUIDCollectionAndRefine(Collection<String> uuids){
        for(String uuid : uuids){
            if(!checkIfValidUUID(uuid)){
                uuids.remove(uuid);
            }
        }
        return uuids;
    }

4
即使在单线程中,这也不安全。 - torquestomp
1
如果每个线程都将传递不同的集合,则没有共享数据。如果没有共享数据,则它是线程安全的。 - dcastro
2个回答

3

每个无效的UUID都会引发一个ConcurrentModificationException异常。

第二点是由于以下原因:

    for(String uuid : uuids){
        if(!checkIfValidUUID(uuid)){
            uuids.remove(uuid);
        }
    }

foreach循环内部创建了一个迭代器,但是你修改了这个迭代器。你需要自己创建一个迭代器并使用.remove()
例如:
final Iterator<String> iterator = uuids.iterator();
String uuid;
while (iterator.hasNext()) {
    uuid = iterator.next();
    if (!checkIfValidUUID(uuid))
        iterator.remove();
}
return uuids;

1
第二点的意思是即使只有一个线程也无法工作。 - user253751
5
第一个观点并不十分确定 - 如果在不同线程中使用的两个集合是不同的集合,则本质上并没有什么线程不安全的问题。而且调用者在方法运行时是无法修改它的...他们正在等待方法完成!另一个线程可能会修改该集合,但调用者肯定不会这样做。 - Jon Skeet
3
“拷贝一份”的想法也不可行——如果另一个线程正在修改集合,那么在你拷贝时就会失败。基本上,你需要使用并发集合或使用同步(在两个线程中都需要)。但我还是认为这个线程本身并不是“不安全的”——它本身没有做任何非线程安全的事情。只是你需要小心,不要使用多个线程共享的集合来调用它。 - Jon Skeet
@所有人:下面的方法是从Spring控制器调用的,传递的集合不是共享的。 - Saurabh Kumar
@JonSkeet的文本已经修复,而且是的,复制也无法工作。这就是为什么我尽可能使用Guava的Immutable*... - fge

-1
你需要将它设置为同步的,以使其线程安全。然后你需要使用迭代器来避免ConcurrentModificationException异常。

1
不需要同步,此方法不与其他线程共享可变状态。 - bowmore
@bowmore 如果两个线程使用相同的“uuids”调用该方法会怎样? - fastcodejava

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接