Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 同步块和变量范围_Java_Multithreading_Thread Safety - Fatal编程技术网

Java 同步块和变量范围

Java 同步块和变量范围,java,multithreading,thread-safety,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);

有谁能向我解释一下,如果两个线程同时访问参数映射,那么在下面的代码中参数映射将受到怎样的影响。映射是否因为不在同步块内而暴露于线程安全问题

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);
    }
}
public void fun(字符串类型、字符串名称、映射参数){
parameters.put(Constants.PARM_TYPE,TYPE);
parameters.put(Constants.PARM_NAME,NAME);
试一试{
同步(启动器){
launcher.launch(类型、布尔值、参数);
}
}捕获(例外e){
logger.error(“啊,世界末日了!”,e);
}
}

我已经看了以下内容,但仍在质疑:

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

如果多个线程对同一个
参数
实例有一个句柄,并且它们使用非线程安全的映射实现调用这个方法(修改映射),那么所有类型的坏事都可能发生(例如,映射损坏,可能/可能不表现为NullPointerException等异常)。

想象一下,如果您有一个共享映射

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

每个线程可能同时更新映射,这可能导致

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

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

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

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


请注意,只需将修改地图的代码行移到同步块中,就不必删除竞争条件,因为您必须考虑应用程序中的其他线程可能会尝试修改地图以及它们将使用哪些对象来同步访问它们。s使用对“launcher”的引用进行同步。如果
参数
实例是独立的(如您在上一篇评论中所述),则任何其他线程在不同步的情况下修改映射,或在与“launcher”不同的对象上进行同步时修改映射,都将导致竞态,则此代码没有问题

方法参数——除了
映射参数
——只有2个
字符串
,因此它们没有同步问题

同步的
块放在方法层或
启动器上:它们是不同的对象。如果你放在方法上,它将在
上同步,否则在
启动器上同步。因为你想保护“启动器”,你必须“建造围栏”尽可能接近-因此在
启动器上同步是可以的


还有另一种技术是使用
objectlockobject=newobject()
,并在该对象上进行同步,但出于此目的,我认为这是过分的,但您可以这样做。

是的,如果该映射不是线程安全的,那么可能会发生各种不好的事情。您需要的是BlockingMap实现。@alexg什么是
BlockingMap
?您是指
ConcurrentMap
参数
rock'n'roll,这会发生。所以参数映射在每个线程中都是一个单独的实例,所以映射中的值应该是可以的,我相信。我相信这里的问题是同步的范围。我正在争论是使方法同步还是将其保持在块级别。在我看来,即使参数对于线程来说是唯一的,因此在执行此代码时在运行时可能仍然存在问题。请具体说明什么类型的异常。这不是一个具体的答案。@GaborSch-i是具体的。”(例如,映射损坏)。甚至可能没有例外。请不要对您不理解的答案进行投票。但可能会有例外。从这个意义上说,甚至可能会发生
ConcurrentModificationException
。因此,您的答案和我的答案一样错误-到目前为止。@GaborSch-当然,可能会有例外。您可能会得到随机的NullPointerException,或o其他东西。如果你认为我的答案事实上是错误的,那好吧。如果你只是恶意的,请删除你的否决票。@GaborSch-不,不会有CME,因为这些只是在迭代过程中抛出的(这里没有发生)。
new Thread(new Runnable(){
    public void run(){
        fun("a","b", map);
    }
}).start();
new Thread(new Runnable(){
    public void run(){
        fun("a","b", map);
    }
}).start();