Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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 - Fatal编程技术网

Java多线程-本地对象引用是否共享?

Java多线程-本地对象引用是否共享?,java,multithreading,Java,Multithreading,我一直在读关于Java多线程的书。我偶然发现了一个关于跨线程资源共享的主题。这让我对本地对象引用有点困惑 对对象的本地引用有点不同。引用本身不共享。但是,引用的对象并不存储在每个线程的本地堆栈中。所有对象都存储在共享堆中如果本地创建的对象从未逃逸创建它的方法,则它是线程安全的。事实上,只要这些方法或对象中没有一个使传递的对象可用于其他线程,您也可以将其传递给其他方法和对象 前几行我可以理解,但是作者用上面粗体的那一行是什么意思?更具体地说,他说的局部逃跑是什么意思 请有人解释一下,可能是用另一个

我一直在读关于Java多线程的书。我偶然发现了一个关于跨线程资源共享的主题。这让我对本地对象引用有点困惑

对对象的本地引用有点不同。引用本身不共享。但是,引用的对象并不存储在每个线程的本地堆栈中。所有对象都存储在共享堆中如果本地创建的对象从未逃逸创建它的方法,则它是线程安全的。事实上,只要这些方法或对象中没有一个使传递的对象可用于其他线程,您也可以将其传递给其他方法和对象

前几行我可以理解,但是作者用上面粗体的那一行是什么意思?更具体地说,他说的局部逃跑是什么意思

请有人解释一下,可能是用另一个例子。

线程安全”意味着不可能因为两个线程同时修改相同的数据而导致对象处于不正确的状态或其他错误;见和


本地创建的对象,即在方法中创建并存储在该方法的本地变量中的对象,通常只能由该方法中的代码访问。当对象
返回
到调用方法或作为参数传递到另一个方法时(包括当调用对象本身的方法时),这些方法获得对它的访问权,并称该对象已转义。然后,这些方法可能会将其发布到其他线程可以看到的地方,并尝试修改它,这可能会导致线程安全问题。但是,如果一个对象从未逃逸,那么可以保证没有其他线程能够访问它,因此,您对对象的使用将始终是线程安全的。

在此测试中,哈希集的使用是线程安全的,因为对它的唯一引用在局部变量中,如果另一个线程进入此方法,它将创建一个新的集

void x() {
    Set s = new HashSet();
    s.add(1);
}
但如果我们将对HashSet的引用保存在一个字段中,那么另一个线程可能会同时更改它

Set s;

void x() {
    s = new HashSet();
    s.add(1);
}

void y() {
    s.add(2);
}

该方法可以由不同的线程调用。并且将为每个调用和每个线程创建一个新实例。但是创建的实例中没有一个可以共享给另一个线程,该实例只存在于本地方法堆栈中

public void someMethod(){
  //First and second thread calls method, both get there own object
  LocalObject localObject = new LocalObject();

  localObject.callMethod();
  method2(localObject);
 }
  //calling next method, own object, too. Instance of the method stack of thread one or two
 public void method2(LocalObject localObject){
   localObject.setValue("value");
 }
考虑相反的情况,类的一个实例成员。两个线程可以调用该方法

InstanceObject instObject;

public void someMethod(){
  //First and second thread calls method, both initialize the member var
  if(instanceObject == null)
      instObject = new InstanceObject ();
  instObject.callMethod();
  method2(localObject);
 }

 public void method2(){
   instObject.setValue("value");
 }
这不是线程安全的。线程调用someMethod并开始初始化instObject。第二条线迟一点来。线程2的instObject也为null。这可能是因为两个原因:

instObject没有完全初始化

instObject的值不会从线程1的内存传递到线程2的内存


当线程一改变instObj时,它期望对象有一个特定的值。但线程2随后出现并更改了该值。或者-更糟糕的是-线程1和线程2更改instObject,但更改只存在于特定线程的内存中。

首先,在方法内部创建的所有本地引用都存储在方法本地堆栈中-因此它们是线程安全的。但在任何方法中创建的对象仍将分配到共享堆空间中。但是,由于您的局部变量指向该对象,因此没有其他变量可以访问它-除非您将句柄分配给来自其他线程(或任何其他非线程安全引用)的其他变量

请在下面找到解释的尝试:

public class Test {
Map<String, String> stringMap = null;

public void method1() {
    Map<String, String> method1Map = new HashMap<String, String>();
    // method1Map.<some method>
    // map is thread safe till now
    method2(method1Map);
}

public void method2(Map<String, String> map) {
    // map.<some method>
    // map is still thread safe till now
    // after the below line the map is no more thread safe as the instance
    // variable got the handle to same map
    this.stringMap = map;
}
公共类测试{
Map stringMap=null;
公共无效方法1(){
Map method1Map=新的HashMap();
//方法1地图。
//到目前为止,地图是线程安全的
方法2(方法1);
}
公共无效方法2(地图){
//地图。
//到目前为止,map仍然是线程安全的
//在下一行之后,映射不再像实例那样是线程安全的
//变量获得了同一映射的句柄
this.stringMap=map;
}
}