Thread(4)-マルチスレッド同期

2656 ワード

コード例:

package com.test;

/**
 *  : 
 * 
 * @author
 * 
 */
public class FetchMoney
{
	public static void main(String[] args)
	{
		Bank bank = new Bank();
		
		Thread t1 = new MoneyThread(bank);// 
		
		Thread t2 = new MoneyThread(bank);// 
		
		t1.start();
		
		t2.start();
		
		
		
	}
}
/**
 *  
 * @author yale
 *
 */
class Bank
{
	private int money = 1000;//  

	//  
	public int getMoney(int number)
	{
		if (number < 0)//  
		{
			return -1;
		}
		else if (number > money)
		{
			return -2;
		}else if(money < 0)
                {
                        return -3;
                }
		else
		{
			try
			{
				// 
				Thread.sleep(1000);
			}
			catch (InterruptedException e)
			{
				e.printStackTrace();
			}
			money -= number;
			
			return number;
		}
	}
}
// 
class MoneyThread extends Thread
{
	private Bank bank;
	
	public MoneyThread(Bank bank)
	{
		this.bank = bank;
	}

	@Override
	public void run()
	{
		System.out.println(bank.getMoney(800));
	}
	
}


出力:

800
800

このような場合、まず2つのスレッドが同じアカウントオブジェクトを構築し、実行するgetMoneyのelseの場合、最初のスレッドが入ってきて、睡眠を開始して、まだ目が覚めていないとき、2番目のスレッドが入ってきて、睡眠も開始し、その後、最初のスレッドが目が覚めて、800を減らして、残りの200、その後、2番目のスレッドが目が覚めて、800を減らして、アカウントが-600になりました
処理方法:アカウントのgetMoney()メソッドを変更し、synchronized(同期)を追加

/**
 *  
 * @author yale
 *
 */
class Bank
{
	private int money = 1000;//  

	//  
	public synchronized int getMoney(int number)
	{
		if (number < 0)//  
		{
			return -1;
		}
		else if (number > money)
		{
			return -2;
		}else if(money < 0)
                {
                        return -3;
                }
		else
		{
			try
			{
				// 
				Thread.sleep(1000);
			}
			catch (InterruptedException e)
			{
				e.printStackTrace();
			}
			money -= number;
			
			return number;
		}
	}
}


 :
800
-2

オブジェクトのsynchronizedメソッドにアクセスするには、例外が解放されるか放出されるまでオブジェクトにロックをかけます.