1

谁能向我解释如果两个线程同时访问参数映射将如何在以下代码中受到影响。映射是否因为不在同步块内而暴露于线程安全问题?

public void fun(String type, String name, Map<String, Object> parameters) {
    parameters.put(Constants.PARM_TYPE, type);
    parameters.put(Constants.PARM_NAME, name);
    try {
        synchronized (launcher) {
            launcher.launch(type, bool, parameters);
        }
    } catch (Exception e) {
        logger.error("AHHHHH, the world has ended!",e);
    }
}

我已经查看了以下内容,但我仍在质疑:同步和可见性范围

4

5 回答 5

1

如果多个线程拥有同一个parameters实例的句柄,并且它们使用非线程安全的映射实现调用此方法(修改映射),则可能/将会发生各种不好的事情(例如,可能/可能不会出现的映射损坏本身作为 NullPointerException 之类的异常)。

于 2013-03-04T16:38:42.697 回答
1

想象一下,如果你有一个共享地图。

private Map<String, Object> map = new HashMap<String,Object>();

如您的示例中所示,许多线程正在更新它。

new Thread(new Runnable(){
    public void run(){
        fun("a","b", map);
    }
}).start();
new Thread(new Runnable(){
    public void run(){
        fun("a","b", map);
    }
}).start();

每个线程可能同时更新地图,这可能会导致美丽的比赛条件

于 2013-03-04T16:41:22.853 回答
1

如果您的parameters实例是独立的(正如您在上一条评论中提到的),那么此代码没有问题。

此外,方法参数Map parameters只有 2String秒,因此不存在关于它们的同步问题。

synchronized块放在方法级别或上launcher:它们是不同的对象。如果你把方法,它会同步 on this,否则 on launcher。既然你想保护“发射器”,你必须尽可能地“建造围栏”——所以同步launcher是可以的。

还有另一种使用Object lockObject = new Object(), 并在该对象上进行同步的技术,但对于这个目的,我认为它是矫枉过正的,但你可以这样做。

于 2013-03-04T17:32:58.543 回答
0

假设多个线程正在访问该方法fun(),map 的工作方式是,如果您多次插入相同的键,那么每次都会覆盖该键的值。但这可能不是唯一的问题。也可能存在竞争条件和腐败问题。如果您想要一个隐式线程安全的数据结构,我认为 aHashTable将完成您的工作。

于 2013-03-04T16:38:18.797 回答
0

如果多个线程同时执行该代码并传递与参数映射相同的对象,那么您将遇到竞争条件

这肯定会导致线程安全问题,除非您:

  • 根据您的要求和 Map 实现并发行为使用正确的 Map 实现(例如ConcurrentHashMap,但这在很大程度上取决于您的应用程序的实际要求)

  • 或自己编写线程安全代码(可能使用“同步”之类的同步原语)。

重要提示:请注意,仅将修改映射的代码行移动到同步块中不一定会消除竞争条件,因为您必须考虑应用程序中的哪些其他线程可能会尝试修改映射以及它们的对象将用于同步他们对它的访问。函数中的代码使用对“启动器”的引用进行同步。任何其他线程修改映射而不同步或在与“启动器”不同的对象上同步将导致竞争条件

于 2013-03-04T17:22:08.300 回答