您的位置:首页 > 其它

多线程同步---synchronize

2016-06-14 21:49 267 查看
       在项目中我们经常遇到这样一种情况:两个人同时操作数据库,导致数据异常。针对于数据库级别我们采用锁机制,还有一种方法使规定我们方法调用的权限,当你在使用这个资源的时候别人是不允许使用的,在多线程中只需要一个修饰词就可以实现:synchronize。
      第一步: 下面我们采用银行取钱的场景来代码实现

Account类:

public class Account {
private String accountNo;
public String getAccountNo() {
return accountNo;
}
public void setAccountNo(String accountNo) {
this.accountNo = accountNo;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
private double balance;
public Account(){

}

public Account(String accountNo,double balance){
this.accountNo=accountNo;
this.balance=balance;
}
public int hashCode(){
return accountNo.hashCode();
}
public boolean equals(Object obj){
if(obj !=null && obj.getClass()==Account.class){
Account target =(Account)obj;
return target.getAccountNo().equals(accountNo);
}
return false;
}
/*public synchronized void draw(double drawAmount){

if(balance >=drawAmount){
System.out.println(Thread.currentThread().getName()+"取钱成功,吐出钞票"+drawAmount);

try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

balance-=drawAmount;
System.out.println("\t余额为:"+balance);

}else{
System.out.println(Thread.currentThread().getName()+"取钱失败!余额不足!");
}
}
*/
}




线程类:
public class DrawThread extends Thread{

private Account account;
private double drawAmount;

public double getDrawAmount() {
return drawAmount;
}
public void setDrawAmount(double drawAmount) {
this.drawAmount = drawAmount;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}

public DrawThread(String name, Account account, double drawAmount){

super(name);
this.account=account;
this.drawAmount=drawAmount;

}

public void run(){

// synchronized(account){
if(account.getBalance() >=drawAmount){
System.out.println(getName()+"取钱成功,吐出钞票"+drawAmount);

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

account.setBalance(account.getBalance()-drawAmount);
System.out.println("\t余额为:"+account.getBalance());

}else{
System.out.println(getName()+"取钱失败!余额不足!");
}
}
/*account.draw(drawAmount);*/

// }
}

client进行测试:
public class TestDraw {
public static void main(String[] args) {

Account acct= new Account("1234567",1000);

new DrawThread("甲",acct,800).start();
new DrawThread("乙",acct,800).start();
}
}

多次执行出现的结果:





     第二步:我们给我们需要执行的逻辑加上synchronize
   run方法下面的synchronized(account)解开注释继续执行,查看结果。

多次执行结果只有:



    解析:当我们加上synchronize修饰词的时候相当于把account类给锁住了,本线程使用account的时候,其他线程不能对account进行编辑。
    第三步:给Account加一个有 synchronize修饰的draw方法,即将代码中的draw注释解除,drawThread方法中也需要改变:
public synchronized void draw(double drawAmount){

if(balance >=drawAmount){
System.out.println(Thread.currentThread().getName()+"取钱成功,吐出钞票"+drawAmount);

try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

balance-=drawAmount;
System.out.println("\t余额为:"+balance);

}else{
System.out.println(Thread.currentThread().getName()+"取钱失败!余额不足!");
}
}
DrawThread中的run方法:

public void run(){
account.draw(drawAmount);
}
执行结果:



总结:
   关于同步方法修饰词synchronize的使用我们分三步来走,第一步,不加修饰词,多次执行会发现偶尔出现错误。第二步,当给Accout实体加入synchronize修饰词后发现多次执行也不会发生错误。第三步,给Account实体加一个有synchronize修饰的draw方法,大家会发现这样虽然效果和第二步是一直的,但是在灵活性上明显是第三步的修改要好很多。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: