Java 在此示例中是否存在同步冲突?

Java 在此示例中是否存在同步冲突?,java,concurrency,synchronized,Java,Concurrency,Synchronized,在我的代码中,我在同一资源的另一个同步块中使用资源set上的同步块。到目前为止,这并没有给我带来任何问题,但我很好奇:如果有什么后果呢?这些同步块是否会相互冲突 Set<myClass> set = Collections.synchronizedSet(new HashSet<myClass>()); synchronized(set) { set.add(new myClass()); ... writeSetContentsToFile()

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

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

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

public synchronized void writeSetContentsToFile() {
    synchronized(set) {
        ...
    }
}
Set Set=Collections.synchronizedSet(新HashSet());
已同步(集){
set.add(新的myClass());
...
writeSetContentsToFile();
}
公共同步的无效writeSetContentsToFile()文件{
已同步(集){
...
}
}

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

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

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

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


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

这里有两个锁,一个在
this
上,另一个在
set
上。如果两个线程以不同的顺序锁定它们,砰。僵局您尚未显示所有代码,因此这可能不可能,但当有人更改类以添加新方法时会发生什么情况


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

这里有两个锁,一个在
this
上,另一个在
set
上。如果两个线程以不同的顺序锁定它们,砰。僵局您尚未显示所有代码,因此这可能不可能,但当有人更改类以添加新方法时会发生什么情况


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

如果您的操作以

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
class
的所有其他非私有方法也同步化
,这样所有操作都将是相互独立的。这样,在这个类中就不需要
synchronized(set)
snippets了


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

如果您的操作以

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
class
的所有其他非私有方法也同步化
,这样所有操作都将是相互独立的。这样,在这个类中就不需要
synchronized(set)
snippets了


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

据我所知,Java同步是特定于线程的,所以这永远不会是一个问题。代码到底是什么让人困惑?当最小值为1时,有四个不同的地方会发生同步。我想不是所有的都需要。如果您使用并发集合,您可能可以避免所有这些集合。该集合由其他线程不断访问和更改。我同步了
writeSetContentsToFile()
,因此文件资源不会有任何冲突,而且
writeSetContentsToFile()
中有一个同步块,以确保在对集合进行迭代时不会对其进行更改。据我所知,Java同步是特定于线程的,所以这永远不会是个问题。代码到底是什么让人困惑?当最小值为1时,有四个不同的地方会发生同步。我想不是所有的都需要。如果您使用并发集合,您可能可以避免所有这些集合。该集合由其他线程不断访问和更改。我同步了
writeSetContentsToFile()
,因此文件资源不会有任何冲突,而且
writeSetContentsToFile()
中有一个同步块,以确保在对集合进行迭代时不对其进行更改。同步块是可重入的,因此在同一线程上,它应该不会引起任何问题。@Daniel可能是在
writeSetContentsToFile()
中重复执行两次
synchronized
,除非
set
不是拥有该方法的类型的成员。通常,您应该使用您拥有的最细粒度的锁,这似乎是
设置的
,以提高吞吐量。同步块是可重入的,因此在同一线程上,它不会导致任何问题。@Daniel可能是在
writeSetContentsToFile()中重复执行两次
同步
,除非
set
不是拥有该方法的类型的成员。通常,您应该使用最细粒度的锁(这里似乎是
set
),以提高吞吐量。