學習筆記 java多線程 信號量(Semaphore),死鎖


   信號量可以用來限制訪問公共資源。在訪問公共資源之前,線程必須從信號量獲取許可。在訪問資源之后,這個線程必須將許可返回給信號量,

 

        為了創建信號量,必須使用可選的公平策略來確定許可的數量。任務通過調用信號量acquire() 方法來獲得許可,可通過調用信號量的release()方法來釋放許可。一旦獲得許可,信號量中可用許可的數量減一。一旦許可唄釋放掉,信號量的可用許可的總數加1。

    

        使用只有一個許可的信號量可以模擬一個相互排斥的鎖。

 

import java.util.concurrent.*;
public class SemaphoreTest
{
	private static  Account _account = new Account();

	public static void main(String[] args) 
	{
       ExecutorService executor = Executors.newCachedThreadPool();
	   for(int i=0; i<100;i++)
		{
			executor.execute(new depositTask());
		}
	    executor.shutdown();
        while(!executor.isTerminated())
		{
		}
		System.out.println("任務完成");
		System.exit(0);
	}

	private static class depositTask implements Runnable
	{
		@Override
		public  void run(){
			_account.deposit(1);	
			
		}
	}

	public static class Account
	{
		private static Semaphore _semaphore = new Semaphore(1,true);
		private int _menoeyy=0;

		private int GetMenoey(){
			return _menoeyy;
		}

		private void deposit(int monery)
		{
			
			try
			{
				_semaphore.acquire();
				_menoeyy+=monery;
				Thread.sleep(50);
				System.out.println(getAccountInfo());
			}
			catch ( InterruptedException ex)
			{
				
			} 
			finally
			{
                _semaphore.release();
			}
			
		}
        
		public  String getAccountInfo(){
			return "當前賬戶與額為:¥"+_menoeyy;
		}
	}
}


避免死鎖

    有時兩個或者多個線程需要在一個共享對象上獲取鎖,這可能導致死鎖(Deadlock),也就是說,每個線程已經鎖定一個對象,而且正在等待另一個對象。下面是一個很可能造成死鎖的例子

  

import java.util.concurrent.*;
public class DeadlockTest 
{
	public static byte[] locker1 = new byte[0];
	public static byte[] locker2 = new byte[0];
	public static void main(String[] args) 
	{
		ExecutorService executor = Executors.newFixedThreadPool(100);
		for(int i =0 ;i <50;i++){
			executor.execute(new DeadlockTask1());
			executor.execute(new DeadlockTask2());
		}
		executor.shutdown();
		while(!executor.isTerminated()){
		
		}
		System.exit(0);
	}

	private static class DeadlockTask1 implements Runnable
	{
		public void run()
		{
			synchronized(locker1){
				System.out.println(" DeadlockTask1 獲得鎖 locker1 沒有死鎖!");
				synchronized(locker2){
					System.out.println(" DeadlockTask1 獲得鎖 locker2 沒有死鎖!");
				}
			}
		}
	}

	private static class DeadlockTask2 implements Runnable
	{
		public void run()
		{
			synchronized(locker2){
				System.out.println(" DeadlockTask2 獲得鎖 locker2 沒有死鎖!");
				synchronized(locker1){
					System.out.println(" DeadlockTask2 獲得鎖 locker1 沒有死鎖!");
				}
			}
		}
	}
}


 

    但是使用資源排序技術就可以輕易的避免死鎖的發生。原理就是為每一個需要鎖的對象排序,確保每個線程都按照這個順序來獲取鎖。假設,按照locker1、locker2的順序對連個對象排序。采用資源排序技術,線程2必須先獲得locker1上的鎖,然后才能獲取lock2上面的鎖。一旦線程1 獲取的locker1上的鎖,線程2必須等待locker1的鎖。所以不會在發生死鎖現象。


 

import java.util.concurrent.*;
public class DeadlockTest 
{
	public static byte[] locker1 = new byte[0];
	public static byte[] locker2 = new byte[0];
	public static void main(String[] args) 
	{
		ExecutorService executor = Executors.newFixedThreadPool(100);
		for(int i =0 ;i <50;i++){
			executor.execute(new DeadlockTask1());
			executor.execute(new DeadlockTask2());
		}
		executor.shutdown();
		while(!executor.isTerminated()){
		
		}
		System.exit(0);
	}

	private static class DeadlockTask1 implements Runnable
	{
		public void run()
		{
			synchronized(locker1){
				System.out.println(" DeadlockTask1 獲得鎖 locker1 沒有死鎖!");
				synchronized(locker2){
					System.out.println(" DeadlockTask1 獲得鎖 locker2 沒有死鎖!");
				}
			}
		}
	}

	private static class DeadlockTask2 implements Runnable
	{
		public void run()
		{
			synchronized(locker1){
				System.out.println(" DeadlockTask2 獲得鎖 locker2 沒有死鎖!");
				synchronized(locker2){
					System.out.println(" DeadlockTask2 獲得鎖 locker1 沒有死鎖!");
				}
			}
		}
	}
}


 

 

       

作者:duanmengchao 發表於2012-5-5 13:05:46 原文鏈接
閱讀:8 評論:0 查看評論

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM