访问由其他线程修改的Set

时间:2012-10-26 12:25:17

标签: java multithreading thread-safety thread-synchronization

有一个ExecutorService有3个主题,每个主题都会将Pair<String,Integer>个对象添加到TreeSet<Pair<String,Integer>>。 addToSet()方法声明为synchronized,一切正常。但是我必须实现一个执行计划任务的新线程,该计划任务必须访问此Set并打印所有值。问题是有时预定的线程崩溃(其他线程工作正常)。我认为它崩溃了,因为在打印机的for循环(预定线程)期间,其他3个线程正在修改Set。

2 个答案:

答案 0 :(得分:1)

您需要在addToSet方法和打印所有值的方法之间互斥。一种方法:

Object setLock = new Object(); // Put this in a scope where all threads can access it

void addToSet( T element ){
    synchronized(setLock) {
       //add it
   }
}

void printAllValues(){
   synchronized(setLock) {
       //print the values
   }
}

答案 1 :(得分:0)

实现此目标的最安全方法是在同步上下文中创建集合的防御副本,并将其用于其他进程。

简单粗略地说:

public void run() {
    TreeSet<...> localSet;
    synchronized (commonSet ) {
        localSet = new TreeSet(commonSet);
    }
    doStuff(localSet);
    ...
}

请注意,这不能解决对集合中对象的并发访问(如果这些是可变的。)