0

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

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

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

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

该集合被其他线程不断地访问和更改。我同步writeSetContentsToFile()了,所以文件资源不会有任何冲突,而且里面有一个同步块writeSetContentsToFile(),以确保在迭代它时不会对集合进行任何更改。

4

3 回答 3

1

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

在某些方面,您回答了自己的问题,它有效,但令人困惑。如果可以的话,最好简化代码。您需要查看其余代码以确定这是否可行。

于 2012-10-04T13:01:54.593 回答
1

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

正如 Peter Lawrey 所说,您应该尝试简化此代码。

于 2012-10-04T13:20:29.833 回答
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
    }
}

ThreadSafeFileStorableSet也制作类的所有其他非私有方法synchronized,因此所有操作对彼此都是原子的。那么你就不需要synchronized (set)这个类中的片段了。

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

于 2012-10-04T13:23:58.067 回答