信号量可以用来限制访问公共资源。在访问公共资源之前,线程必须从信号量获取许可。在访问资源之后,这个线程必须将许可返回给信号量,

 

        为了创建信号量,必须使用可选的公平策略来确定许可的数量。任务通过调用信号量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 查看评论

 

 posted on 2012-05-05 13:06  小段段  阅读(6658)  评论(0编辑  收藏  举报