Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/apache-flex/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_Synchronization_Thread Safety - Fatal编程技术网

java中的同步提供意外输出

java中的同步提供意外输出,java,multithreading,synchronization,thread-safety,Java,Multithreading,Synchronization,Thread Safety,我翻阅了一本书,看到一段代码,上面说下面的代码是线程同步的: //帐户类别 public class Account { private double balance; public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } public synchronized void addAmount(doub

我翻阅了一本书,看到一段代码,上面说下面的代码是线程同步的:

//帐户类别

 public class Account {

 private double balance;

 public double getBalance() {
 return balance;
}

 public void setBalance(double balance) {
 this.balance = balance;
}


 public synchronized void addAmount(double amount) {
 double tmp=balance;
 try {
 Thread.sleep(10);
 } catch (InterruptedException e) {
   e.printStackTrace();
 }
 tmp+=amount;
 balance=tmp;
}


public synchronized void subtractAmount(double amount) {
  double tmp=balance;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
tmp-=amount;
balance=tmp;
}

}
//银行类

public class Bank implements Runnable {

 private Account account;
 public Bank(Account account) {
  this.account=account; 
}

@Override

public void run() {

for (int i=0; i<1000; i++){

     account.subtractAmount(1000);
  }
 }
}
在这里,两个不同对象的两个线程使用addAmount和subtractAmount函数同时更改平衡变量,但它始终提供正确的输出,因为初始和最终平衡相同,即1000.000。我的意思是他们应该告诉我一些问题,因为两个线程同时处理同一个变量

请纠正我哪里出错了。
提前感谢

这就是同步的全部要点。它确保一次只有一个线程可以执行该函数。

这就是同步的全部要点。它确保一次只能有一个线程执行该函数。

在Java中,每个对象都有一个intrisinc锁,使用synchronize关键字表示当线程(我们称之为a)调用该方法时,线程a持有锁。当线程A持有锁时,其他线程将被阻止访问对象的同步部分(在您的例子中是Account对象)

一旦线程A完成了同步块(或本例中的方法)的执行,线程A就会释放对象上的锁,等待访问Account对象的其他线程现在可以继续

  • 首先,同一对象上的两个同步方法调用不可能交错。当一个线程正在执行时 一个对象的同步方法,所有其他调用 同一对象块的同步方法(暂停执行) 直到第一个线程处理完对象
  • 其次,当同步方法退出时,它会自动与任何后续方法建立“发生在之前”的关系 为同一对象调用同步方法。这 保证对对象状态的更改对所有人都可见 线程
有关使用synchronized的更多详细信息,请参阅

实际上,为了使帐户线程安全,您需要同步setter并将余额声明为volatile:

public class Account {

 private volatile double balance;

 public double getBalance() {
 return balance;
 }

 public synchronized void setBalance(double balance) {
 this.balance = balance;
}
//其余的代码已经同步 }


有关volatile用法的更多信息,请参阅。

在Java中,每个对象都有一个intrisinc锁,使用synchronize关键字表示当线程(我们称之为a)调用该方法时,线程a持有锁。当线程A持有锁时,其他线程将被阻止访问对象的同步部分(在您的例子中是Account对象)

一旦线程A完成了同步块(或本例中的方法)的执行,线程A就会释放对象上的锁,等待访问Account对象的其他线程现在可以继续

  • 首先,同一对象上的两个同步方法调用不可能交错。当一个线程正在执行时 一个对象的同步方法,所有其他调用 同一对象块的同步方法(暂停执行) 直到第一个线程处理完对象
  • 其次,当同步方法退出时,它会自动与任何后续方法建立“发生在之前”的关系 为同一对象调用同步方法。这 保证对对象状态的更改对所有人都可见 线程
有关使用synchronized的更多详细信息,请参阅

实际上,为了使帐户线程安全,您需要同步setter并将余额声明为volatile:

public class Account {

 private volatile double balance;

 public double getBalance() {
 return balance;
 }

 public synchronized void setBalance(double balance) {
 this.balance = balance;
}
//其余的代码已经同步 }


有关volatile用法的更多信息,请参见。

这就是为什么要使用
synchronized
实际上,这本书并不完全正确。您可以设置未同步的余额。只有加法和减法是正确的。你能告诉我们这本书是什么吗?这就是为什么你使用
synchronized
实际上,这本书并不完全正确。您可以设置未同步的余额。只有加法和减法是正确的。你能告诉我们这是什么书吗?
public class Account {

 private volatile double balance;

 public double getBalance() {
 return balance;
 }

 public synchronized void setBalance(double balance) {
 this.balance = balance;
}