正确同步在主线程中创建并传递到新线程的地图对象

时间:2011-01-24 07:37:39

标签: java map synchronization

我正在尝试开发一个程序来接收存储在地图中的数据请求。地图在main方法中声明,如下所示:

Map m = Collections.synchronizedMap(new HashMap());
synchronized(m) {
        while (listening) {

            new BrokerLookupServerHandlerThread(serverSocket.accept(), m).start();

        }
}

BrokerLookupServerHandlerThread的代码获取输入并使其成为对象变量之一。如果我在这个课程中使用它,原始地图也会更新吗?我知道Java是通过值传递的,(我习惯于C / C ++)所以我只是想确定同步对象的这种实现是否有意义。

    private Socket socket = null;
//private String t ="MSFT";
public Map m;

public BrokerLookupServerHandlerThread(Socket socket, Map m) {
    super("NamingServerHandlerThread");
    this.socket = socket;
    this.m = m;
    System.out.println("Created new Thread to handle client");
}

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

是的,两个线程都会看到对地图所做的更改。

Java确实使用pass by value - 但在这种情况下,值是一个引用(类似于指针)。 Java中引用类型变量的值始终是对象的引用,或者为null。它永远不是对象本身。

因此您的代码不会创建新地图。很少有操作隐式创建新对象。我只能想到使用字符串文字(无论如何都是文字内容)和原始类型的自动装箱。除此之外,您只能通过new运算符获取新对象。 (显然你调用的任何方法都可以创建一个新对象......)

请注意,这与线程之间的同步问题完全不同。有关复制对象与复制引用的业务与线程正交。在这种情况下,您似乎已使用Collections.synchronizedMap解决了线程方面问题;正如Pangea所说,您可能希望使用ConcurrentHashMap而不会使用几乎同样多的锁定(如果有的话)。 ConcurrentMap接口的另一个实现是ConcurrentSkipListMap。查看两个课程的文档,以确定最适合您的课程。

答案 1 :(得分:1)

是原始对象将被更新。我建议您使用ConcurrentHashMap

  

支持完整的哈希表   检索和并发   可调节的预期并发性   更新。这门课也服从同样的道理   功能规范为Hashtable,   并包括方法的版本   对应于每种方法   哈希表。但是,尽管如此   操作是线程安全的,   检索操作不需要锁定,也没有   支持锁定整个表   以阻止所有访问的方式。   这个类可以完全互操作   Hashtable在依赖于它的程序中   线程安全,但没有   同步细节。