Java线程同步之synchronized方法

在介绍synchronized方法之前,我们先来分析下面的代码

 

 

 

/*
 * 线程不安全,取钱问题
 * */
public class UnsafeTest02 {
	public static void main(String[] args) {
		//账户
		Account account=new Account(100, "存款");
		Drawing myDrawing =new Drawing(account, 50, "我");
		Drawing HisDrawing =new Drawing(account, 70, "爸爸");
                myDrawing.start();
                HisDrawing.start();
		
		
		
	}

}
class Account{
	int money;
	String nameString;
	public Account(int money, String nameString) {
		super();
		this.money = money;
		this.nameString = nameString;
	}	
	 
}

class Drawing extends Thread{
	Account account;
	int drawingMoney;
	
	
	public Drawing(Account account, int drawingMoney,String name) {
		super(name);
		this.account = account;
		this.drawingMoney = drawingMoney;
		
		
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		if(account.money<drawingMoney) {
			System.out.println("余额不足");
			return;
		}
		//模拟网络延时
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		account.money-=drawingMoney;
		
		System.out.println(this.getName()+"--->总共取了"+drawingMoney+"--->账户余额为"+account.money);
		
	}
}	
我--->总共取了50--->账户余额为50
爸爸--->总共取了70--->账户余额为-20

我和爸爸共用一个银行账户,账户里面有100元。有一天,我和爸爸在对方不知情的情况下同时取钱。我想取50元,爸爸想取70元。我和爸爸同时都操作银行账户取钱,可能我在柜台取钱,爸爸用银行卡在自动取款机取钱。我和爸爸同时发起取钱线程,但是我这边操作更快,先取得了对账户的控制权,先对账户进行取50元,但是由于线程延时Thread.Sleep(100),我还未来得及修改账户中还剩下的余额,爸爸那头也在操作取70元。所有出现了银行余额为-20。这类情况被称为线程同步不安全。如何解决这样的情况?我们引入了synchronized修饰方法。

下面代码是操作同步代码块

public class SynTest02 {
	public static void main(String[] args) {
		//账户
		Account account=new Account(100, "存款");
		SafeDrawing myDrawing =new SafeDrawing(account, 50, "我");
		SafeDrawing HisDrawing =new  SafeDrawing(account, 70, "爸爸");
                myDrawing.start();
                HisDrawing.start();
		
		
		
	}

}

class Account{
	int money;
	String nameString;
	public Account(int money, String nameString) {
		super();
		this.money = money;
		this.nameString = nameString;
	}	
	 
}


class SafeDrawing extends Thread{
	Account account;
	int drawingMoney;
	
	
	public SafeDrawing(Account account, int drawingMoney,String name) {
		super(name);
		this.account = account;
		this.drawingMoney = drawingMoney;
		
		
	}

	@Override
	public void  run() {
		// TODO Auto-generated method stub
                //使用account为同步监视器,任何线程在进入下面的同步代码块之前
               //必须先获得account账户的锁,-----其他线程无法获得锁,无法修改Account
		synchronized (account) {
			if(account.money<drawingMoney) {
				System.out.println(this.getName()+"---余额不足");
				return;
			}
			
			//模拟网络延时
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
                        //修改余额
                        account.money-=drawingMoney;
			
			System.out.println(this.getName()+"--->总共取了"+drawingMoney+"--->账户余额为"+account.money);
			
		}
		
	}
      //同步代码块结束,释放锁


}
我--->总共取了50--->账户余额为50
爸爸--->余额不足

引入synchronized方法可以解决线程不同步的问题。

上述代码是操作同步代码块,如果sysnchronized直接修饰方法,同步方法如下

public class SynTest02 {
	public static void main(String[] args) {
		//账户
		Account1 account=new Account1(100, "存款");
		SafeDrawing myDrawing =new SafeDrawing(account, 50, "我");
		SafeDrawing HisDrawing =new  SafeDrawing(account, 70, "爸爸");
        myDrawing.start();
        HisDrawing.start();
		
		
		
	}

}

class Account1{
	//账户总共的钱
	int money;
	//账户名称
	String nameString;
	//要取的钱
	int drawingTotal;
	public Account1(int money, String nameString) {
		super();
		this.money = money;
		this.nameString = nameString;
	}
	//同步方法
	public synchronized void Drawing(int drawingMoney) {
		if(money<drawingMoney) {
			System.out.println(Thread.currentThread().getName()+"---取钱失败,余额不足");
			return;
		}
		//模拟网络延时
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		money-=drawingMoney;
		System.out.println(Thread.currentThread().getName()+"--->总共取了"+drawingMoney+"--->账户余额为"+money);	
						
				
	 
       }
}


class SafeDrawing extends Thread{
	Account1 account;
	int drawingMoney;
	public SafeDrawing(Account1 account, int drawingMoney,String name) {
		super(name);
		this.account = account;
		this.drawingMoney = drawingMoney;
		
		
	}
	@Override
	public void  run() {
		// TODO Auto-generated method stub
		account.Drawing(drawingMoney);			
	}
	
}
我--->总共取了50--->账户余额为50
爸爸---取钱失败,余额不足

 

关于Synchoronized的使用,如下表

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值