/**
 * 
 */
package thread;/**
 * @description 线程同步
 *
 */
public class SynchronizedTest {
public static void main(String[] args) {
Account account = new Account("10011",0);
new DepositThread2("存钱线程",account,300).start();
new DrawThread2("取钱线程",account,300).start();
}
}
/**
 * @description 账户-存/取
 *
 */
class Account2{
private String accountNo;
private double balance;//余额
private boolean flag = false;//true代表可取 ,false代表可存
public Account2(String accountNo,double balance) {
this.accountNo = accountNo;
this.balance = balance;
}
/**
 * @return the accountNo
 */
public String getAccountNo() {
return accountNo;
}
/**
 * @param accountNo the accountNo to set
 */
public void setAccountNo(String accountNo) {
this.accountNo = accountNo;
}
/**
 * @return the balance
 */
public double getBalance() {
return balance;
}
/**
 * @description 取钱
 * @param drawAmount
 */
public synchronized void draw(double drawAmount){
try{
if(flag){//flag=true , 表示账户还有钱,等待将钱取走
System.out.println(Thread.currentThread().getName()+" 取钱:"+drawAmount);
balance -= drawAmount;
System.out.println("账户余额:"+balance);
flag = false;//可以存钱
notifyAll();
}else{
wait();
}
}catch(Exception e){
}
}

/**
 * @description 存钱
 * @param drawAmount
 */
public synchronized void deposit(double depositAmount){
try{
if(flag){//flag=true , 表示账户还有钱,等待将钱取走
wait();
}else{
System.out.println(Thread.currentThread().getName()+" 存钱:"+depositAmount);
balance += depositAmount;
System.out.println("账户余额:"+balance);
flag = true;//可以取钱
notifyAll();
}
} catch (InterruptedException e) {
}
}
}
/**
 * @decription 存钱线程
 *
 */
class DepositThread2 extends Thread{
private Account account;
private double drawAmount=300;

public DepositThread2(String name,Account account,double drawAmount) {
super(name);
this.account = account;
this.drawAmount = drawAmount;
}
/* (non-Javadoc)
 * @see java.lang.Thread#run()
 */
@Override
public void run() {
for(int i=0;i<5;i++){
account.deposit(drawAmount);
}
}
}
/**
 * @decription 取钱线程
 *
 */
class DrawThread2 extends Thread{
private Account account;
private double drawAmount = 300;

public DrawThread2(String name,Account account,double drawAmount) {
super(name);
this.account = account;
this.drawAmount = drawAmount;
}
/* (non-Javadoc)
 * @see java.lang.Thread#run()
 */
@Override
public void run() {
for(int i=0;i<5;i++){
account.draw(drawAmount);
}
}
}
在存钱线程里使用循环存了5次钱,每次存后再等待取钱线程取钱.  从控制台的输出:只存了3次或4次, 并且程序偶尔不能结束.  
请问是不是死锁了, 要如何解决?

解决方案 »

  1.   

    wait具有假唤醒线程的现象出现,因此要采用while来判断不是采用if
    将存钱和取钱的if(flag)改为while(flag)逻辑请自己研究下。
      

  2.   

    package thread;import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;/**
     * @description 线程同步
     */
    public class LockTest {
    public static void main(String[] args) {
    Account account = new Account("10011",0);
    new DepositThread("存钱线程",account,300).start();
    new DrawThread("取钱线程",account,300).start();
    }
    }
    /**
     * @description 账户-存/取
     */
    class Account{
    private final Lock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();
    private String accountNo;
    private double balance;//余额
    private boolean flag = false;//true代表可取 ,false代表可存
    public Account(String accountNo,double balance) {
    this.accountNo = accountNo;
    this.balance = balance;
    }
    /**
     * @return the accountNo
     */
    public String getAccountNo() {
    return accountNo;
    }
    /**
     * @param accountNo the accountNo to set
     */
    public void setAccountNo(String accountNo) {
    this.accountNo = accountNo;
    }
    /**
     * @return the balance
     */
    public double getBalance() {
    return balance;
    }
    /**
     * @description 取钱
     * @param drawAmount
     */
    public void draw(double drawAmount){
    lock.lock();//加锁
    try{
    if(flag){//flag=true , 表示账户还有钱,等待将钱取走
    System.out.println(Thread.currentThread().getName()+" 取钱:"+drawAmount);
    balance -= drawAmount;
    System.out.println("账户余额:"+balance);
    flag = false;//可以存钱
    condition.signal();
    }else{
    condition.await();
    }
    } catch (InterruptedException e) {
    e.printStackTrace();
    }finally{
    lock.unlock();//解锁
    }
    }

    /**
     * @description 存钱
     * @param drawAmount
     */
    public void deposit(double depositAmount){
    lock.lock();//加锁
    try{
    if(flag){//flag=true , 表示账户还有钱,等待将钱取走
    condition.await();
    }else{
    System.out.println(Thread.currentThread().getName()+" 存钱:"+depositAmount);
    balance += depositAmount;
    System.out.println("账户余额:"+balance);
    flag = true;//可以取钱
    condition.signal();
    }
    } catch (InterruptedException e) {
    e.printStackTrace();
    }finally{
    lock.unlock();//解锁
    }
    }
    }
    /**
     * @decription 存钱线程
     */
    class DepositThread extends Thread{ private Account account;
    private double drawAmount=300;

    public DepositThread(String name,Account account,double drawAmount) {
    super(name);
    this.account = account;
    this.drawAmount = drawAmount;
    } /* (non-Javadoc)
     * @see java.lang.Thread#run()
     */
    @Override
    public void run() {
    for(int i=0;i<5;i++){
    account.deposit(drawAmount);
    }
    }
    }
    /**
     * @decription 取钱线程
     * @author wang_kang
     *
     */
    class DrawThread extends Thread{
    private Account account;
    private double drawAmount = 300;

    public DrawThread(String name,Account account,double drawAmount) {
    super(name);
    this.account = account;
    this.drawAmount = drawAmount;
    }
    /* (non-Javadoc)
     * @see java.lang.Thread#run()
     */
    @Override
    public void run() {
    for(int i=0;i<5;i++){
    account.draw(drawAmount);
    }
    }

    }用lock也是一样呢
      

  3.   

    换成while可行.谢谢~package thread;
    /**
     * @description 线程同步
     *
     */
    public class SynchronizedTest {
        public static void main(String[] args) {
            Account2 account = new Account2("10011",0);
            new DepositThread2("存钱线程",account,300).start();
            new DrawThread2("取钱线程",account,300).start();
        }
    }
    /**
     * @description 账户-存/取
     *
     */
    class Account2{
        private String accountNo;
        private double balance;//余额
        private boolean flag = false;//true代表可取 ,false代表可存
        public Account2(String accountNo,double balance) {
            this.accountNo = accountNo;
            this.balance = balance;
        }
        /**
         * @return the accountNo
         */
        public String getAccountNo() {
            return accountNo;
        }
        /**
         * @param accountNo the accountNo to set
         */
        public void setAccountNo(String accountNo) {
            this.accountNo = accountNo;
        }
        /**
         * @return the balance
         */
        public double getBalance() {
            return balance;
        }
        /**
         * @description 取钱
         * @param drawAmount
         */
        public synchronized void draw(double drawAmount){
            try{
             while(!flag){
             wait();
             }
                if(flag){//flag=true , 表示账户还有钱,等待将钱取走
                    System.out.println(Thread.currentThread().getName()+" 取钱:"+drawAmount);
                    balance -= drawAmount;
                    System.out.println("账户余额:"+balance);
                    flag = false;//可以存钱
                    notifyAll();
                }
            }catch(Exception e){
            }
        }
        
        /**
         * @description 存钱
         * @param drawAmount
         */
        public synchronized void deposit(double depositAmount){
            try{
             while(flag){
             wait();
             }
                if(!flag){//flag=true , 表示账户还有钱,等待将钱取走
                 System.out.println(Thread.currentThread().getName()+" 存钱:"+depositAmount);
                    balance += depositAmount;
                    System.out.println("账户余额:"+balance);
                    flag = true;//可以取钱
                    notifyAll();
                }
            } catch (InterruptedException e) {
            }
        }
    }
    /**
     * @decription 存钱线程
     *
     */
    class DepositThread2 extends Thread{
        private Account2 account;
        private double drawAmount=300;
        
        public DepositThread2(String name,Account2 account,double drawAmount) {
            super(name);
            this.account = account;
            this.drawAmount = drawAmount;
        }
        /* (non-Javadoc)
         * @see java.lang.Thread#run()
         */
        @Override
        public void run() {
            for(int i=0;i<5;i++){
                account.deposit(drawAmount);
            }
        }
    }
    /**
     * @decription 取钱线程
     *
     */
    class DrawThread2 extends Thread{
        private Account2 account;
        private double drawAmount = 300;
        
        public DrawThread2(String name,Account2 account,double drawAmount) {
            super(name);
            this.account = account;
            this.drawAmount = drawAmount;
        }
        /* (non-Javadoc)
         * @see java.lang.Thread#run()
         */
        @Override
        public void run() {
            for(int i=0;i<5;i++){
                account.draw(drawAmount);
            }
        }
    }