从线程内部修改外部对象

时间:2022-06-09 01:09:40
public void fooAndBar() {
    HashMap<Foo, Bar> fooBarMap = new HashMap<>();
    CompletionService completionService = new ExecutorCompletionService(exec);

    for(int i=0; i<10; i++) {
        completionService.submit(new Callable() {
            @Override
            public Void call() throws Exception {
                fooBarMap.put(new Foo(i), new Bar(i));
                return null;
            }
        });
    }
}
  • Is it safe to modify the HashMap inside the Callable?

    修改Callable中的HashMap是否安全?

  • Should the hashmap be final (or maybe volatile) and if so, why?

    hashmap应该是final(或者可能是volatile),如果是,为什么?

  • Should I use a structure other than HashMap, something like ConcurrentHashMap or SynchronizedMap and why?

    我应该使用除HashMap之外的结构,比如ConcurrentHashMap或SynchronizedMap,为什么?

I'm trying to grasp java concepts so please bear with me

我正在努力掌握java概念,所以请耐心等待

2 个解决方案

#1


2  

Is it safe to modify the HashMap inside the Callable?

修改Callable中的HashMap是否安全?

No. If you are using a threadpool I assume you are planning to have more of those callables running in parallel. Any time an object with mutable state is accessed from more than one thread, that's thread-unsafe. If you write to a thread-unsafe hashmap from two threads simultaneously, its internal structure will be corrupted. If you read from a thread-unsafe hashmap while another thread is writing to it simultaneously, your reading thread will read garbage. This is a very well known and extensively studied situation known as a Race Condition, a description of which would be totally beyond the scope of this answer. For more information, read about Race Condition on Wikipedia or on another question answered back in 2008: * - What is a Race Condition.

不。如果您使用的是线程池我假设您计划让更多的这些callables并行运行。任何时候从多个线程访问具有可变状态的对象,这是线程不安全的。如果同时从两个线程写入线程不安全的hashmap,其内部结构将被破坏。如果你从一个线程不安全的hashmap读取而另一个线程同时写入它,你的读取线程将读取垃圾。这是一个众所周知且广泛研究的情况,称为种族条件,其描述将完全超出本答案的范围。有关更多信息,请阅读*上的竞争条件或2008年回答的另一个问题:* - 什么是竞争条件。

Should the hashmap be final (or maybe volatile) and if so, why?

hashmap应该是final(或者可能是volatile),如果是,为什么?

For your purposes it does not need to be final, but it is always a good practice to make final anything that can be made final.

为了您的目的,它不需要是最终的,但最终做出最终的任何事情总是一个好习惯。

It does not need to be volatile because:

它不需要是volatile,因为:

  • if you were to make it volatile, you would be making the reference to it volatile, but the reference never changes, it is its contents that change, and volatile has nothing to do with those.

    如果你要使它变得不稳定,那么你会将它的引用变为volatile,但是引用永远不会改变,它的内容会发生变化,而volatile也与它们无关。

  • the threadpool makes sure that call() will be executed after fooBarMap = new HashMap<>(). (If you are wondering why such a thing could ever be a concern, google for "memory boundary".)

    threadpool确保在fooBarMap = new HashMap <>()之后执行call()。 (如果你想知道为什么这样的事情可能成为一个问题,谷歌的“内存边界”。)

Should I use a structure other than HashMap, something like ConcurrentHashMap or SynchronizedMap and why?

我应该使用除HashMap之外的结构,比如ConcurrentHashMap或SynchronizedMap,为什么?

Definitely. Because, as I wrote earlier, any time an object with mutable state is accessed from more than one thread, that's thread-unsafe. And ConcurrentHashMap, SynchronizedMap, synchronize, etc. exist precisely for taking care of thread-unsafe situations.

当然。因为,正如我之前所写,任何时候从多个线程访问具有可变状态的对象,这是线程不安全的。并且ConcurrentHashMap,SynchronizedMap,synchronize等正好用于处理线程不安全的情况。

#2


-4  

Hashmap should not be final, as you are modifying it multiple times(from within a for loop).

Hashmap不应该是最终的,因为您要多次修改它(从for循环中)。

If you make it final, you may get an error.

如果你最终成功,你可能会收到错误。

#1


2  

Is it safe to modify the HashMap inside the Callable?

修改Callable中的HashMap是否安全?

No. If you are using a threadpool I assume you are planning to have more of those callables running in parallel. Any time an object with mutable state is accessed from more than one thread, that's thread-unsafe. If you write to a thread-unsafe hashmap from two threads simultaneously, its internal structure will be corrupted. If you read from a thread-unsafe hashmap while another thread is writing to it simultaneously, your reading thread will read garbage. This is a very well known and extensively studied situation known as a Race Condition, a description of which would be totally beyond the scope of this answer. For more information, read about Race Condition on Wikipedia or on another question answered back in 2008: * - What is a Race Condition.

不。如果您使用的是线程池我假设您计划让更多的这些callables并行运行。任何时候从多个线程访问具有可变状态的对象,这是线程不安全的。如果同时从两个线程写入线程不安全的hashmap,其内部结构将被破坏。如果你从一个线程不安全的hashmap读取而另一个线程同时写入它,你的读取线程将读取垃圾。这是一个众所周知且广泛研究的情况,称为种族条件,其描述将完全超出本答案的范围。有关更多信息,请阅读*上的竞争条件或2008年回答的另一个问题:* - 什么是竞争条件。

Should the hashmap be final (or maybe volatile) and if so, why?

hashmap应该是final(或者可能是volatile),如果是,为什么?

For your purposes it does not need to be final, but it is always a good practice to make final anything that can be made final.

为了您的目的,它不需要是最终的,但最终做出最终的任何事情总是一个好习惯。

It does not need to be volatile because:

它不需要是volatile,因为:

  • if you were to make it volatile, you would be making the reference to it volatile, but the reference never changes, it is its contents that change, and volatile has nothing to do with those.

    如果你要使它变得不稳定,那么你会将它的引用变为volatile,但是引用永远不会改变,它的内容会发生变化,而volatile也与它们无关。

  • the threadpool makes sure that call() will be executed after fooBarMap = new HashMap<>(). (If you are wondering why such a thing could ever be a concern, google for "memory boundary".)

    threadpool确保在fooBarMap = new HashMap <>()之后执行call()。 (如果你想知道为什么这样的事情可能成为一个问题,谷歌的“内存边界”。)

Should I use a structure other than HashMap, something like ConcurrentHashMap or SynchronizedMap and why?

我应该使用除HashMap之外的结构,比如ConcurrentHashMap或SynchronizedMap,为什么?

Definitely. Because, as I wrote earlier, any time an object with mutable state is accessed from more than one thread, that's thread-unsafe. And ConcurrentHashMap, SynchronizedMap, synchronize, etc. exist precisely for taking care of thread-unsafe situations.

当然。因为,正如我之前所写,任何时候从多个线程访问具有可变状态的对象,这是线程不安全的。并且ConcurrentHashMap,SynchronizedMap,synchronize等正好用于处理线程不安全的情况。

#2


-4  

Hashmap should not be final, as you are modifying it multiple times(from within a for loop).

Hashmap不应该是最终的,因为您要多次修改它(从for循环中)。

If you make it final, you may get an error.

如果你最终成功,你可能会收到错误。