线程的同步

线程的同步:

  由于同一进程的多个线程共享存储空间,在带来方便的同时也带来访问冲突的问题。例如在本例中若两个线程同时访问变量balance,会造成结果不符合实际要求的情况,在本例中描述为:一个账号余额为1000元,两个或多个线程同时进行取款1000元操作,但取款操作后结果出现余额为负数,这与实际情况余额应该大于0元的结果不符。

  在java中引入了“对象互斥锁”的概念来实现对不同线程的共享数据操作的同步。“对象互斥锁”不允许多个线程同时访问同一个条件变量(即共享数据)。实质上,是把多个线程对象并行的访问数据共享改为串行的访问数据,即同一时刻最多只有一个对象访问共享数据。

  java中针对方法提出一套机制,就是synchronized关键字,它包括两种用法:synchronized修饰方法和synchronized修饰程序块。

本例中定义了3个类:
Bank(定义银行账号),Operation(线程类,实现存/取款操作)和TestBankOperation(主类)
本例中实现线程同步的方法:
1)给public void deposite(double dmount)和 public void withdrawal(double dmount)方法加锁,
即加上关键字 synchronized
2)在取款和存款的过程中给bank对象加锁

public class TestBankOperation {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Bank bank = new Bank("1002",1000);
        //创建线程的方法一:继承Thread类
        new Operation(1+"# ",bank,1000).start();
        new Operation(0+"# ",bank,1000).start();
        new Operation(3+"# ",bank,1000).start();
        /*
        //创建线程的方法二:实现Runnable接口
        Operation o = new Operation("#",bank,1000);
        Thread t1 = new Thread(o);
        Thread t2 = new Thread(o);
        Thread t3 = new Thread(o);
        t1.start();
        t2.start();
        t3.start();
        */
    }
}

/*
 *线程类,实现了同步取款操作
 */
class Operation extends Thread
//class Operation implements Runnable
{
    Bank bank;
    double mount;
    String name;
    public Operation(String name)
    {
        super(name);
        //this.name = name;
    }
    public Operation(String name,Bank bank,double dmount)
    {
        super(name);
        //this.name = name;
        this.bank = bank;
        this.mount = dmount;
    }
    /*
    public void run()
    {
        //bank.deposite(mount);
        bank.withdrawal(mount);
    }
    */
    public void run()
    {
        synchronized(bank)
        {
            bank.withdrawal(mount);
        }    
    }
}
/*
 * 银行账号类
 */
class Bank
{
    
    String account;//账号
    double balance;//余额
    Bank(String account,double balance)
    {
        this.setAccount(account);
        this.balance = balance;
    }
    //设置账号
    public void setAccount(String account)
    {
        this.account = account;
    }
    //设置余额
    public void setBalance(double balance)
    {
        this.balance = balance;
    }
    //获取账号
    public String getAccount()
    {
        return this.account;
    }
    //获取余额
    public double getBanlance()
    {
        return this.balance;
    }
    /*
     * 存款
     * @param dmount存款金额
     */
    public void deposite(double dmount)
    //public synchronized void deposite(double dmount)
    {
        this.setBalance(this.getBanlance()+dmount);
        System.out.println(Thread.currentThread().getName()+"线程存款成功!  "+"存款为:" + dmount + "   当前余额为:" + this.balance+"
");
    }
    
    /*
     * 取款操作
     * @param dmount 取款金额
     */
    public void withdrawal(double dmount)
    //public synchronized void withdrawal(double dmount)
    {
        if(dmount <= this.balance)
        {
            System.out.println(Thread.currentThread().getName()+"线程取款成功!  "+"吐出钞票为:" + dmount);
            this.setBalance(this.balance-dmount);
            System.out.println("当前余额为:" + this.balance+"
");
        }
        else
            System.out.println("余额不足!");
    }
        
}

某次运行结果:

原文地址:https://www.cnblogs.com/UUUP/p/3811755.html