在这种情况下,同步语句如何工作?

时间:2010-10-08 05:33:40

标签: java multithreading concurrency synchronization synchronized

假设我有这样的课程:

public class Server {

   public static void main(String[] args) {

      Map<Integer, ServerThread> registry = Collections.synchronizedMap(new LinkedHashMap<Integer, ServerThread>());

      ...

      while(true) {
         Socket socket = serverSocket.accept();
         ServerThread serverThread = new ServerThread(id, registry);
         registry.put(id, serverThread);
      }
   }
}

然后:

public class ServerThread extends Thread {

   private Map<Integer, ServerThread> registry;
   private int id;

   public ServerThread(int id, Map<Integer, ServerThread> registry) {
      this.id = id;
      this.registry = registry;
   }

   ...

   private void notify() {
      synchronized(registry) {
         for(ServerThread serverThread : registry.values()) {
            serverThread.callSomePublicMethodOnThread();
         }
      }      
   }
}

我只是想确保在迭代它时registry没有被修改。使它成为同步映射可以保证这种行为吗?或者我需要synchronized声明。同步语句的行为是否与我期望的一样?

由于

4 个答案:

答案 0 :(得分:5)

循环周围需要synchronized块。

有关详细信息,请参阅JavaDoc

答案 1 :(得分:2)

是的,你所拥有的同步语句将像你期望的那样工作。我只想添加一条注释,你接受套接字连接的线程将阻塞在registry.put(id,serverThread);当你在另一个线程的同步部分。这意味着您在处理通知时服务器不会处理任何新的传入请求.....

您可能需要考虑移动put语句(当然将serverThread更改为此) 到ServerThread的run方法的run方法的第一行。这样,如果callSomePublicMethodOnThread需要花费很长时间来处理,你就不会阻止传入连接。

答案 2 :(得分:1)

为了让一切变得简单,我将使用ConcurrentHashMap(http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ConcurrentHashMap.html),因此您无需使用循环中的同步块,因为concurrentHashMap使用不同类型的迭代器(不是故障快速迭代器),并且它不会使并发兼容更改,你也会有更好的性能。

答案 3 :(得分:0)

代码中存在一个问题,您无法将方法定义为“private void notify()”,因为“notify()”是Object类中定义的方法