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,我想知道以下类是否是线程安全的: class Example { private Thing thing; public setThing(Thing thing) { this.thing = thing; } public use() { thing.function(); } } 具体来说,如果一个线程通过Example::use调用setThing,而另一个线程在Thing::function中,会发生什么情况 例如: Example exampl

我想知道以下类是否是线程安全的:

class Example {

private Thing thing;

public setThing(Thing thing) {
    this.thing = thing;
    }

public use() {
    thing.function();
    }
}
具体来说,如果一个线程通过Example::use调用setThing,而另一个线程在Thing::function中,会发生什么情况

例如:

Example example = new Example();
example.setThing(new Thing());

createThread(example);  // create first thread
createThread(example);  // create second thread



具体地说,我想知道,当use()执行时调用setThing时,它会成功地继续使用旧对象,还是会以某种方式更新对该对象的引用导致问题。

如果该方法正在共享资源而线程未同步,然后,它们会发生冲突,可能会出现几种情况,包括覆盖由另一个线程计算并存储在共享变量中的数据


如果该方法只有局部变量,那么您可以通过多线程使用该方法,而无需担心竞速。但是,通常非助手类在其方法中操纵成员变量,因此建议使方法同步,或者如果您确切知道问题可能发生的位置,则使用
final
lock/object锁定(也称为同步)方法的子范围

对SpecificUCAR类的螺纹安全性进行推理时,有两点:

  • 线程之间共享状态的可见性
  • 多线程通过类方法使用类对象时的安全性(保留类不变量)
  • 示例
    类的共享状态仅由一个
    对象组成

  • 从可见性的角度来看,该类不是线程安全的。一个线程的
    设置结果
    不会被其他线程看到,因此它们可以处理过时的数据。NPE也是可以接受的,因为类初始化期间
    thing
    的初始值为
    null
  • 通过
    use
    方法访问
    Thing
    类而不使用其源代码是不可能的。但是,
    Example
    调用
    use
    方法而不进行任何同步,否则
    Example
    就不是线程安全的

  • 因此,
    示例
    不是线程安全的。要修复点1,如果您确实需要setter,您可以将
    volatile
    添加到
    thing
    字段,或者将其标记为final并在构造函数中初始化。确保满足2的最简单方法是将
    use
    标记为
    synchronized
    。如果将
    setThing
    标记为
    synchronized
    ,则不再需要
    volatile
    。然而,还有许多其他复杂的技术可以满足第2点的要求。这本好书更详细地描述了这里写的所有内容。

    第二个线程可能会看到新的值,也可能看不到。如果它确实看到了它,它可能还没有完全构建好。取决于
    Thing
    的线程安全性。
    Thing
    在您的示例中永远不会为空,因为变量赋值在Java中是原子的(除了long和double)。但是,在thread2将旧对象设置为新值后,thread1仍可能使用旧对象。将事物声明为volatile以避免这种情况。thread1将始终使用相同的方法完成
    函数()
    方法的执行-Object@rollback,你明确回答了我的问题,请随意回答。我会更新我的问题,因为你用好话表达了我无法表达的东西。任何文件都将不胜感激。
    //Thread1
    while(1) {
      example.use();
    }
    
    //Thread2
    while(1) {
        sleep(3600000); //yes, i know to use a scheduled thread executor
        setThing(new Thing());
    }