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_Runnable - Fatal编程技术网

Java 是否可以在线程中更新属性

Java 是否可以在线程中更新属性,java,multithreading,runnable,Java,Multithreading,Runnable,假设我创建了一个对象,并在线程中运行它,类似这样 public class Main { public static void main(String[] args) { SomeClass p = new SomeClass (143); p.start(); p.updateNumber(144); }} 是否可以使用methode UpdateEnumber()将SomeClass中传递的参数更新为fallows: #更新 结果: 144 144 144 14

假设我创建了一个对象,并在线程中运行它,类似这样

public class Main {

public static void main(String[] args) {
    SomeClass p = new SomeClass (143);
    p.start();
    p.updateNumber(144);

}}
是否可以使用methode UpdateEnumber()将SomeClass中传递的参数更新为fallows:

#更新

结果: 144 144 144 144 144


谢谢

是的,但是您需要将
数字
声明为,或者()使用a而不是

数字声明为
易失性

什么时候需要

当多个线程使用相同的 变量,每个线程将有其 拥有该服务器的本地缓存的副本 变量所以,当它更新 值,它实际上在 本地缓存不在主变量中 记忆。另一根线是 使用同一个变量并不知道 有关于被更改的值的任何信息吗 这是另一条线。为了避免这种情况 问题是,如果将变量声明为 易失性,则不会存储它 在本地缓存中。每当线程 如果正在更新值,它将被更新 到主存储器。那么,其他线程 可以访问更新的值


SomeClass
即使它是可运行的,它也只是一个普通类,任何引用它的线程都可以访问它的对象。在你的例子中。您没有在任何地方调用
updateNumber()
form,但是如果在p.start()之后调用它,则是从实际生成实例的线程访问它。如果您在
run()
中调用
updateNumber()
,那么您将从刚刚启动的线程访问它


另一个问题是:在设置中从多个线程更改它是否安全?答案是否定的。如果根据当前值更改,则必须将其声明为
volatile
(比方说),或者
synchronize
。同步的方式和内容取决于您对它的实际操作。

是的,您可以调用
p.updateNumber(…)
,但您需要注意线程同步问题

当满足以下所有条件时,您可以使用关键字
volatile

  • 对变量的写入不依赖于其当前值,或者您可以确保只有一个线程更新该值
  • 该变量不参与其他状态变量的不变量
  • 在访问变量时,不需要出于任何其他原因进行锁定
否则,我建议使用某种同步策略

class SomeClass implements Runnable {
    private Integer number;
    SomeClass (int number) {
        this.number = Integer.valueOf(number);
    }

    @Override
    public void run() {
        while(true){
           System.out.println(getNumber());
        }
    }

  public void updateNumber(int n){
      synchronized(number){
          number = Integer.valueOf(n);
      }
  }     

  public int getNumber(){
      synchronized(number){
          return number.intValue();
      }
  }
}

另一个没有提到的选项是使用Doug Lee在Java 1.5中引入的并发包,这是您应该使用的选项,而不是上面提到的同步

使用原子类,这些类可以解决所有并发问题。(在一定程度上)

大概是这样的:

 private AtomicInteger number = new AtomicInteger(0);

 public void updateNumber(int n) {
   number.getAndSet(n);
 }

 public int getNumber() {
   return number.get();
 }

在我看来,《实践中的Java并发》是关于Java线程的最好的书


这可能需要同步一个可能同步的方法,或者进程间通信。
long
的长度为64位,在32位机器上更新它需要两个(非原子)操作,所以您可能会得到一个混乱的值,其中包含来自不同值的低位和高位。您应该
同步
setter方法或使用
原子长
。同步在这里是必不可少的。但是,您必须将变量声明为volatile,以确保该值将是最新的oneUpdate:我检查了最新的JLS,并且写入声明为volatile的
long
确实是一个原子操作,因此您最初的建议是可以的。。。不需要额外的同步。@Moh,如果只有一个线程(在本例中是主线程)调用
updateNumber
,那么使用关键字
volatile
就足够了。:)但在结果中,为什么143的值没有出现?它直接从144开始,我甚至在考试前就睡了一觉sysout@Moh,您还需要在读取时进行同步。请使用
getNumber()
方法查看我的编辑。在
number
上同步不是一个好主意,尤其是在同步的块内重新指定其值时。一个好的替代方法是使用单独的对象,例如
objectlock=newobject()。。。已同步(锁定){…}
或仅使方法本身
同步
。但实际上,只要使用
AtomicInteger
@mattball,我完全同意,我很高兴你发表了这样的评论。我只是想告诉@Moh,数字的读写需要同步,或者至少是原子的。在过去,我发现使用原子数据类型仍然需要根据情况进行同步。。。
 private AtomicInteger number = new AtomicInteger(0);

 public void updateNumber(int n) {
   number.getAndSet(n);
 }

 public int getNumber() {
   return number.get();
 }