简体   繁体   English

Java 并发与集合

[英]Java Concurrency with Sets

For the below function, I am trying to return a new Set mHashSet that is a copy of another set iGraphicSectors :对于下面的函数,我试图返回一个新的 Set mHashSet ,它是另一个集合iGraphicSectors的副本:

public Set<String> getGraphics() {
    synchronized (iGraphicSectors) {  // class variable of type Set<String>
        LinkedHashSet<String> mHashSet = new LinkedHashSet<String>();
        synchronized (mHashSet) {
            mHashSet.addAll(iGraphicSectors);
        }
        return mHashSet;
    }
}

However line 5 mHashSet.addAll(iGraphicSectors);然而第 5 行mHashSet.addAll(iGraphicSectors); is throwing a ConcurrentModificationException (I am not sure how this is possible).正在抛出ConcurrentModificationException (我不确定这怎么可能)。 Is there a way I can accomplish the above task in a thread-safe manner?有没有办法以线程安全的方式完成上述任务?

What you need to do is to use a Set that is thread-safe for iGraphicSectors as you obviously read and modify it concurrently, the simplest way can be to use the decorator Collections.synchronizedSet(Set<T> s) to make your current Set thread-safe, any read and write accesses will then be automatically protected with a synchronized block thanks to the decorator, however you still need to protect iterations over it explicitly with a synchronized block.您需要做的是对iGraphicSectors使用线程安全的Set ,因为您显然是同时读取和修改它的,最简单的方法是使用装饰器Collections.synchronizedSet(Set<T> s)来制作当前的Set线程安全,由于装饰器,任何读取和写入访问都将使用synchronized块自动保护,但是您仍然需要使用synchronized块显式保护它的迭代。

Here is an example of how to create it:以下是如何创建它的示例:

Set<String> iGraphicSectors = Collections.synchronizedSet(new HashSet<String>());

Here is how your code would then look like:以下是您的代码的外观:

public Set<String> getGraphics() {
    // Still needed as the constructor of LinkedHashSet will iterate
    // over iGraphicSectors 
    synchronized (iGraphicSectors) {  
        return new LinkedHashSet<String>(iGraphicSectors);
    }
}

From your latest comments, it sounds like you simply want to make the Set immutable - which you can do without using any synchronization primitives with :从您的最新评论中,听起来您只是想让Set不可变 - 您可以在不使用任何同步原语的情况下做到这一点:

return Collections.unmodifiableSet(iGraphicSectors);

at the end of this function (See the docs ).在此函数的末尾(请参阅文档)。

As a side note, it's fairly obvious that you don't want to use synchronization, as the Set is constructed locally within the function.作为旁注,很明显您不想使用同步,因为Set是在函数内部构造的。 It does not have any visibility to other threads executing in your program.它对程序中执行的其他线程没有任何可见性。 If any synchronization is to take place, it's not in this method .如果要进行任何同步,则不在此方法中

The real question is, will the Set returned by this method change?真正的问题是,这个方法返回的Set会改变吗? If so, you can return a synchronized Set from this function with:如果是这样,你可以从这个函数返回一个同步的Set

return Collections.synchronizedSet(...)

at the end of this function (again, see the docs ).在此函数的末尾(再次参见文档)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM