2017-03-03 25 views
1

我经历了一本书,看到说,下面代码的代码是线程同步:同步在java中给人意想不到的输出

// Account类

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。我的意思是他们应该是我的一些问题,因为这两个线程同时在同一个变量上工作。

请纠正我在哪里错了。 预先感谢

+1

这就是为什么你使用'同步' – QBrute

+0

其实,这本书是不完全正确的。您可以设置天平不同步。只有加和减是。你能告诉我们它是什么书吗? – Fildor

回答

0

这就是同步的整点。它确保一次只有一个线程可以执行该功能。

0

在Java中会发生什么情况是,每个对象都有一个intrisinc锁,使用同步关键字表明,当一个线程(我们称之为A)调用这个方法,线程A持有锁。当线程A持有锁时,其他线程将被阻止访问对象的同步部分(在您的情况下是Account对象)。

一旦线程A已完成执行(在这种情况下或方法)同步块,线程A释放对象上的锁,以及其他线程正在等待访问您的帐户对象现在可以继续前进。

  • 首先,它是不可能的同一对象上同步方法来交错两个调用。当一个线程正在执行 同步方法为对象,即调用 针对同一对象块同步方法所有其他线程,直到第一线程与对象进行(暂停执行) 。
  • 其次,当一个同步方法退出时,它自动地建立一个之前发生的关系与任何后续 调用针对同一对象同步方法进行说明。此 保证对所有 线程都可见对象状态的更改。

上使用的同步详情见https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

实际上使帐户线程安全的,你会希望有二传手同步和平衡被声明为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更多关于不稳定的使用。