同步块和可变范围

时间:2013-03-04 16:30:23

标签: java multithreading thread-safety

如果两个线程同时访问参数映射,那么任何人都可以向我解释如何在以下代码中影响参数映射。地图是否暴露于线程安全问题,因为它不在同步块内?

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);
    }
}

我看过以下内容,但我仍在质疑:Synchronized and the scope of visibility

5 个答案:

答案 0 :(得分:1)

如果多个线程具有相同parameters实例的句柄,并且他们使用非线程安全的地图实现调用此方法(修改地图),则会发生各种不良事件(例如,映射损坏,可能/可能不会将自身表现为NullPointerException等异常。

答案 1 :(得分: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();

每个帖子可能会同时更新地图,这可能会导致A Beautiful Race Condition

答案 2 :(得分:1)

如果您的parameters个实例是(正如您在上次评论中提到的那样),那么此代码就没有问题。

方法参数 - 除了Map parameters - 只有2 String s,因此没有关于它们的同步问题。

synchronized块放到方法级别或launcher上:它们是不同的对象。如果您使用方法,它将在this上同步,否则在launcher上同步。由于你想要保护'启动器',你必须尽可能地“建立围栏” - 所以在launcher上同步是可以的。

还有另一种使用Object lockObject = new Object()的技术,并对该对象进行同步,但对于这种情况,我认为这样做太过分了,但你可以这样做。

答案 3 :(得分:0)

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

答案 4 :(得分:0)

如果多个线程执行该代码并同时传递与参数映射相同的对象,那么您将拥有race condition

除非您:

,否则这肯定会导致线程安全问题
  • 根据您的要求和Map实现并发行为(例如ConcurrentHashMap)使用正确的Map实现,但这很大程度上取决于您应用的实际要求)

  • 或自己编写线程安全代码(可能使用'synchronized'等同步原语。)

重要提示:请注意,只需将修改地图的代码行移动到同步块中,就不一定会删除竞争条件,因为您必须考虑应用中的其他线程可能会尝试修改地图以及他们将使用哪个对象来同步对它的访问权限。函数中的代码使用对'launcher'的引用进行同步。任何其他线程修改地图而不同步或通过不同于'启动器'的对象进行同步将导致竞争条件