多线程同步---synchronize

Posted wangdan1030

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程同步---synchronize相关的知识,希望对你有一定的参考价值。

       在项目中我们经常遇到这样一种情况:两个人同时操作数据库,导致数据异常。针对于数据库级别我们采用锁机制,还有一种方法使规定我们方法调用的权限,当你在使用这个资源的时候别人是不允许使用的,在多线程中只需要一个修饰词就可以实现: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方法,大家会发现这样虽然效果和第二步是一直的,但是在灵活性上明显是第三步的修改要好很多。

以上是关于多线程同步---synchronize的主要内容,如果未能解决你的问题,请参考以下文章

java多线程核心技术——synchronized同步方法与synchronized同步快

在一般程序开发中可以使用synchronized同步多线程

Java多线程-synchronized同步方法及同步块简述

Java多线程的同步机制(synchronized)

synchronized锁多线程同步的原理是咋样的?

Java多线程同步 synchronized 关键字的使用