代码之家  ›  专栏  ›  技术社区  ›  Vivin Paliath

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

  •  0
  • Vivin Paliath  · 技术社区  · 14 年前

    假设我有这样一门课:

    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 陈述。synchronized语句是否会像我期望的那样运行?

    谢谢

    4 回复  |  直到 14 年前
        1
  •  5
  •   ChrisH    14 年前

    你需要 synchronized 绕着圈堵住。

    JavaDoc 详细情况。

        2
  •  2
  •   user439407    14 年前

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

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

        3
  •  1
  •   punkers    14 年前

    为了使一切更容易,我将使用ConcurrentHashMap(http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ConcurrentHashMap.html)所以您不需要在循环中使用sync块,因为concurrentHashMap使用不同类型的迭代器(不是fail fast迭代器),它不会引发concurrentModificationException,你也会有更好的表现。

        4
  •  0
  •   miz    13 年前

    代码中有一个问题,不能将方法定义为“private void notify()”,因为“notify()”是在对象类中定义的方法