我正在阅读一本书并看到一段代码,该代码表明下面的代码是线程同步的:
//帐户类
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);
}
}
}
//公司类
public class Company implements Runnable {
private Account account;
public Company(Account account) {
this.account=account;
}
@Override
public void run() {
for (int i=0; i<1000; i++){
account.addAmount(1000);
}
}
}
//主要课程
public class Main {
public static void main(String[] args) {
Account account=new Account();
account.setBalance(1000);
Company company=new Company(account);
Thread companyThread=new Thread(company);
Bank bank=new Bank(account);
Thread bankThread=new Thread(bank);
System.out.printf("Account : Initial Balance: %f\n",account.
getBalance());
companyThread.start();
bankThread.start();
try {
companyThread.join();
bankThread.join();
System.out.printf("Account : Final Balance: %f\n",account.
getBalance());
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
这里两个不同对象的两个线程正在使用addAmount和subtractAmount函数同时更改平衡变量,但它始终给出正确的输出作为初始和最终余额相同,即1000.000。我的意思是他们应该有一些问题,因为两个线程同时处理同一个变量。
请纠正我的错误。 提前谢谢
答案 0 :(得分:0)
这是同步的全部要点。它确保一次只有一个线程可以执行该功能。
答案 1 :(得分:0)
Java中发生的事情是每个对象都有一个intrisinc锁,并且使用synchronize关键字表示当一个Thread(让我们称之为A)调用该方法时,线程A持有锁。当线程A持有锁时,其他线程将被阻止访问Object的同步部分(在您的情况下为Account对象)。
一旦线程A完成执行同步块(或本例中的方法),线程A就会释放对象的锁定,而等待访问您的Account对象的其他线程现在可以继续前进。
- 首先,对同一对象的两个同步方法的调用不可能进行交错。当一个线程正在执行时 对象的同步方法,所有其他调用的线程 同一对象块的同步方法(暂停执行) 直到第一个线程完成对象。
- 其次,当同步方法退出时,它会自动建立与之后的任何关系 调用同一对象的同步方法。这个 保证所有人都可以看到对象状态的变化 线程。
有关使用synchronized的详细信息,请参阅https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html。
实际上为了使Account线程安全,您可能希望将setter同步并将余额声明为volatile:
public class Account {
private volatile double balance;
public double getBalance() {
return balance;
}
public synchronized void setBalance(double balance) {
this.balance = balance;
}
//其余代码已经同步 }
有关易失性用途的更多信息,请参阅https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html。