在这个给定的例子中是否存在同步冲突?

时间:2012-10-04 12:59:30

标签: java concurrency synchronized

在我的代码中,我在同一资源上另一个同步块内的资源set上使用了一个synchronized块。到目前为止,这并没有给我带来任何问题,但我很好奇:如果有的话后果是什么?这些同步块会相互冲突吗?

Set<myClass> set = Collections.synchronizedSet(new HashSet<myClass>());

synchronized(set) {
    set.add(new myClass());
    ...
    writeSetContentsToFile();
}

public synchronized void writeSetContentsToFile() {
    synchronized(set) {
        ...
    }
}

该组由其他线程连续访问和更改。我同步writeSetContentsToFile(),因此文件资源不会有任何冲突,同样,writeSetContentsToFile()内有一个同步块,以确保迭代时不会对该集进行任何更改

3 个答案:

答案 0 :(得分:1)

  

到目前为止,这并没有给我带来任何问题,但我很好奇:如果有的话会有什么后果?

在某种程度上,你回答了自己的问题,但这有点令人困惑。如果可以,最好简化代码。您需要查看其余代码以确定是否可行。

答案 1 :(得分:1)

这里有两个锁,this上有一个,set上有一个锁。如果两个线程以不同的顺序锁定它们,那就是BANG。僵局。您没有显示所有代码,因此可能无法实现,但是当有人更改类以添加新方法时呢?

正如Peter Lawrey所说,你应该尝试简化这段代码。

答案 2 :(得分:1)

如果您的操作以

表示
synchronized(set) {
    set.add(new myClass());
    ...
    writeSetContentsToFile();
}

是原子的,将其封装在单独的类中,比如ThreadSafeFileStorableSet,在专用方法下,比如synchronized writeContentsToFile()

例如:

class ThreadSafeFileStorableSet {
    private final Set set;

    ThreadSafeFileStorableSet(Set set) {
        this.set = set;
    }

    synchronized void writeSetContentsToFile() {
        // 
    }

    synchronized void addElements(Object[] elems) {
        // 
    }

    private void doWrite() {
        // use instance set
    }
}

使ThreadSafeFileStorableSetsynchronized的所有其他非私有方法也是如此,因此所有操作都将彼此原子化。那么你不需要在这个课程中使用synchronized (set)个片段。

这将简化您的代码,但可能会使并发级别更糟。但是我没有足够的信息来告诉您阅读代码会变得多糟糕。