Java发生之前和线程安全

Cap*_*ngs 10 java concurrency multithreading thread-safety happens-before

假设我有一个包装HashMap的类,如下所示:

public final class MyClass{

     private final Map<String, String> map;

     //Called by Thread1
     public MyClass( int size ){
         this.map = new HashMap<String, String>( size );
     }

     //Only ever called by Thread2
     public final String put( String key, String val ){
        return map.put( key, value );
     }

     //Only ever called by Thread2
     public final String get( String key ){
        return map.get( key );
     }

     //Only ever called by Thread2
     public final void printMap(  ){
       //Format and print the contents of the map
     }

}
Run Code Online (Sandbox Code Playgroud)

该类通过"Thread1"初始化.但是,put,get,printMap和其他操作只能由"Thread2"调用.

我是否正确理解这个类是线程安全的:

  1. 由于对map的引用被声明为final,所有其他线程都会看到map的初始状态(之前发生).

  2. 由于put/get/printMap/etc仅由Thread2调用,因此不需要互斥.

谢谢

Gre*_*lli 9

所以你要问的是正确的假设.如果可以保证只使用这种方式,则不需要使其成为线程安全的.你不能在java中传递一半构造的对象,因此"构造函数可能无法完成"是不可能的.

所以,如果你这样做

new Thread(new Runnable() {

    public void run() {
          final MyClass instance = new MyClass(10);
          new Thread(new Runnable() {
               public void run() {
                    instance.put("one", "one");
                      ....
               }

           }).start();
     }

}).start();
Run Code Online (Sandbox Code Playgroud)

你很好:)这就是你所描述的,由Thread1创建但仅由Thread2使用.线程无法与自身发生冲突.

线程安全是一个不同的定义,其中组合实体可以安全地与多个线程交互.在您描述的情况下,该场景不会发生,因为您基本上有一个构造的线程和另一个操作的线程.

  • 我不能说m0skit0的动机,只是我的.我发布了我的评论,因为在构造函数返回之前无法看到对象这一概念非常直观,而且可能是常见的 - 但却是错误的.你的代码工作的唯一原因是`Thread.start()`创建了一个明确的先发生边(内部是有趣的边).你_can_在构造函数完成之前看到一个对象.如果不出意外的话,我想对任何可能看到你答案并将其作为证据支持他们(错误的)直觉的人说出谨慎的话. (3认同)
  • 我不认为我很密集,没有理由变得粗鲁.我没有贬低你.我只是在指出你所写的事实上的不准确之处. (2认同)