Lock ReentrantLock tryLock condtion 用法

12 篇文章 1 订阅

ReentrantLock 可重入锁指的是   同一个线程可多次获取同一把锁

 

package test.BingFa;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class TestLock {

	final static ExecutorService exec = Executors.newFixedThreadPool(4);

	final static ReentrantLock lock = new ReentrantLock();

	final Condition con = lock.newCondition();

	final int time = 3;

	static Runnable add = new Runnable() {

		public void run() {

			System.out.println("Pre " + lock);

			lock.lock();

			try {
				System.out.println("试图获取锁 ");
				// con.await(time, TimeUnit.SECONDS);
			}
			// catch (InterruptedException e) {
			//
			// e.printStackTrace();
			//
			// }
			finally {
				// con.signal();
				System.out.println("Post " + lock.toString());

				lock.unlock();

			}

		}
	};

	static Runnable addTryLock = new Runnable() {
		public void run() {
			System.out.println("Pre " + lock);
			while (true) {
				if (lock.tryLock()) {
					try {
						System.out.println("试图获取锁 ");
						// con.await(time, TimeUnit.SECONDS);
					}
					// catch (InterruptedException e) {
					//
					// e.printStackTrace();
					//
					// }
					finally {
						// con.signal();
						System.out.println("Post " + lock.toString());
						lock.unlock();
					}
					break; //不然 无限制执行
				}
			}

		}
	};

	public static void main(String[] args) throws InterruptedException {

		for (int index = 0; index < 4; index++)

		 exec.submit(add);
			//exec.submit(addTryLock);
		exec.shutdown();

	}
}
	//exec.submit(addTryLock);

打开可以测试 try lock

 

 

以下转载

 

Lock和Condition

 

1、jdk1.5之前用synchornized和voatile来控制共享对象的并发访问,jdk5.0提供了ReentrantLock。

2、Lock和ReentrantLock:

 

Lock接口里定义了一些抽象的锁操作,有无条件、可轮询、定时、可中断的锁获取操作,ReentrantLock实现了Lock接口,获得ReetrantLock的锁与进入synchronized代码块有相同的内存语义,释放ReentrantLock锁和退出sychronized代码块有相同的内存语义。

 

从上面可以看出,Lock提供了不同形式获取锁方式,而之前通过synchronied修饰代码块的时候,如果有一个线程已经获取对象锁,其他线程访问共享对象的时候就必须无限等待,等待当前线程释放对象锁后再去进行竞争,不能中断那些等待获取锁的线程,而Lock提供了一些其他方法,比如tryLock():如果当前锁可用则获取并返回true,如果不可用则返回false。在方法前加上while(true)就可以实现轮询获取锁。

Java代码  收藏代码

  1. package com.sxit.test;  
  2.   
  3. import java.util.concurrent.locks.Lock;  
  4. import java.util.concurrent.locks.ReentrantLock;  
  5.   
  6. /** 
  7.  * @功能:tryLock使用 
  8.  * @作者: smile 
  9.  * @时间:2013-4-18 下午4:03:18 
  10.  * @版本:1.0 
  11.  */  
  12. public class TryLockDemo {  
  13.   
  14.     // 锁  
  15.     private final Lock lock = new ReentrantLock();  
  16.   
  17.     public void take() {  
  18.             if (lock.tryLock()) {  
  19.                 try {  
  20.                     System.out.println("take获取到锁...");  
  21.                 } catch (Exception e) {  
  22.                     e.printStackTrace();  
  23.                 } finally{  
  24.                     lock.unlock();  
  25.                 }  
  26.             }else{  
  27.                 System.out.println("take没有获取到锁...");  
  28.             }  
  29.     }  
  30.   
  31.     public void put() {  
  32.             if (lock.tryLock()) {  
  33.                 try {  
  34.                     System.out.println("put获取到锁...");  
  35.                 } catch (Exception e) {  
  36.                     e.printStackTrace();  
  37.                 } finally{  
  38.                     lock.unlock();  
  39.                 }  
  40.             }else{  
  41.                 System.out.println("put没有获取到锁...");  
  42.             }  
  43.     }  
  44.   
  45.     public static void main(String[] args) {  
  46.   
  47.         TryLockDemo t = new TryLockDemo();  
  48.         Take take = new Take(t);  
  49.         Put put = new Put(t);  
  50.         Thread t1 = new Thread(take);  
  51.         Thread t2 = new Thread(put);  
  52.   
  53.         t1.start();  
  54.         t2.start();  
  55.     }  
  56. }  
  57.   
  58. class Take implements Runnable {  
  59.   
  60.     private TryLockDemo t;  
  61.   
  62.     public Take(TryLockDemo t) {  
  63.         this.t = t;  
  64.     }  
  65.   
  66.     @Override  
  67.     public void run() {  
  68.         while (true) {  
  69.             try {  
  70.                 Thread.sleep(1000);  
  71.             } catch (InterruptedException e) {  
  72.                 e.printStackTrace();  
  73.             }  
  74.             t.take();  
  75.         }  
  76.     }  
  77. }  
  78.   
  79. class Put implements Runnable {  
  80.   
  81.     private TryLockDemo t;  
  82.   
  83.     public Put(TryLockDemo t) {  
  84.         this.t = t;  
  85.     }  
  86.   
  87.     @Override  
  88.     public void run() {  
  89.         while (true) {  
  90.             try {  
  91.                 Thread.sleep(1000);  
  92.             } catch (InterruptedException e) {  
  93.                 e.printStackTrace();  
  94.             }  
  95.             t.put();  
  96.         }  
  97.     }  
  98. }  

 

 

通过使用tryLock方法就可以让那些等待线程可以不用再无限期等待,可以继续轮询获取锁或者做其他操作。

tryLock还有一个指定时间获取锁的方法,在指定时间内如果锁可用则返回,不可用则线程处于休眠状态。

Java代码  收藏代码

  1. package com.sxit.test;  
  2.   
  3. import java.util.concurrent.TimeUnit;  
  4. import java.util.concurrent.locks.Lock;  
  5. import java.util.concurrent.locks.ReentrantLock;  
  6.   
  7. /** 
  8.  * @功能:tryLock使用 
  9.  * @作者: smile 
  10.  * @时间:2013-4-18 下午4:03:18 
  11.  * @版本:1.0 
  12.  */  
  13. public class TryLockDemo {  
  14.   
  15.     // 锁  
  16.     private final Lock lock = new ReentrantLock();  
  17.   
  18.     public void take() throws Exception {  
  19.             if (lock.tryLock(100,TimeUnit.NANOSECONDS)) {  
  20.                 try {  
  21.                     System.out.println("take获取到锁...");  
  22.                 } catch (Exception e) {  
  23.                     e.printStackTrace();  
  24.                 } finally{  
  25.                     lock.unlock();  
  26.                 }  
  27.             }else{  
  28.                 System.out.println("take 100纳秒内没有获取到锁...");  
  29.             }  
  30.     }  
  31.   
  32.     public void put() throws Exception {  
  33.             if (lock.tryLock(100,TimeUnit.NANOSECONDS)) {  
  34.                 try {  
  35.                     System.out.println("put获取到锁...");  
  36.                 } catch (Exception e) {  
  37.                     e.printStackTrace();  
  38.                 } finally{  
  39.                     lock.unlock();  
  40.                 }  
  41.             }else{  
  42.                 System.out.println("put 100纳秒内没有获取到锁...");  
  43.             }  
  44.     }  
  45.   
  46.     public static void main(String[] args) {  
  47.   
  48.         TryLockDemo t = new TryLockDemo();  
  49.         Take take = new Take(t);  
  50.         Put put = new Put(t);  
  51.         Thread t1 = new Thread(take);  
  52.         Thread t2 = new Thread(put);  
  53.   
  54.         t1.start();  
  55.         t2.start();  
  56.     }  
  57. }  
  58.   
  59. class Take implements Runnable {  
  60.   
  61.     private TryLockDemo t;  
  62.   
  63.     public Take(TryLockDemo t) {  
  64.         this.t = t;  
  65.     }  
  66.   
  67.     @Override  
  68.     public void run() {  
  69.         while (true) {  
  70.             try {  
  71.                 t.take();  
  72.             } catch (InterruptedException e) {  
  73.                 e.printStackTrace();  
  74.             } catch (Exception e) {  
  75.                 e.printStackTrace();  
  76.             }  
  77.         }  
  78.     }  
  79. }  
  80.   
  81. class Put implements Runnable {  
  82.   
  83.     private TryLockDemo t;  
  84.   
  85.     public Put(TryLockDemo t) {  
  86.         this.t = t;  
  87.     }  
  88.   
  89.     @Override  
  90.     public void run() {  
  91.         while (true) {  
  92.             try {  
  93.                 t.put();  
  94.             } catch (InterruptedException e) {  
  95.                 e.printStackTrace();  
  96.             } catch (Exception e) {  
  97.                 e.printStackTrace();  
  98.             }  
  99.         }  
  100.     }  
  101. }  

 还有一种是lockInterruptibly():可中断的锁获取,当线程在获取锁的时候,如果有其他线程调用该线程的interrupt方法中断线程,这时不会再去尝试获取锁,而会抛出一个InterruptedException异常。而正常的lock()方法不允许中断线程,即使调用了interrupt()方法还是会继续尝试获取锁,最后获取到锁后再把线程设置为interrupt状态,然后再中断。 而且使用lockInterruptibly获取锁的时候,如果线程被中断了,会抛出异常,并且会把线程的中断状态移除。

 

Java代码  收藏代码

  1. package com.sxit.test;  
  2.   
  3. import java.util.concurrent.TimeUnit;  
  4. import java.util.concurrent.locks.Lock;  
  5. import java.util.concurrent.locks.ReentrantLock;  
  6.   
  7. /** 
  8.  * @功能:lockInterruptibly使用 
  9.  * @作者: smile 
  10.  * @时间:2013-4-18 下午4:03:18 
  11.  * @版本:1.0 
  12.  */  
  13. public class TryLockDemo {  
  14.   
  15.     // 锁  
  16.     private final Lock lock = new ReentrantLock();  
  17.   
  18.     public void interrupt() {  
  19.         try {  
  20.             lock.lockInterruptibly();  
  21.             System.out.println("打印一下");  
  22.             //中断前状态  
  23.             System.out.println("中断前状态:"+Thread.currentThread().isInterrupted());  
  24.             //中断当前线程  
  25.             Thread.currentThread().interrupt();  
  26.             //中断后状态  
  27.             System.out.println("中断后状态:"+Thread.currentThread().isInterrupted());  
  28.         } catch (InterruptedException e) {  
  29.             e.printStackTrace();  
  30.         } finally {  
  31.             //中断最后状态  
  32.             System.out.println("中断最后状态:"+Thread.currentThread().isInterrupted());  
  33.             lock.unlock();  
  34.         }  
  35.     }  
  36.   
  37.     public static void main(String[] args) {  
  38.   
  39.         TryLockDemo t = new TryLockDemo();  
  40.         Iterrupt i = new Iterrupt(t);  
  41.         Thread t1 = new Thread(i);  
  42.           
  43.         t1.start();  
  44.           
  45.     }  
  46. }  
  47.   
  48.   
  49. class Iterrupt implements Runnable {  
  50.   
  51.     private TryLockDemo t;  
  52.   
  53.     public Iterrupt(TryLockDemo t) {  
  54.         this.t = t;  
  55.     }  
  56.   
  57.     @Override  
  58.     public void run() {  
  59.         while (true) {  
  60.             try {  
  61.                 t.interrupt();  
  62.             } catch (Exception e) {  
  63.                 e.printStackTrace();  
  64.             }  
  65.         }  
  66.     }  
  67. }  

 

还有一个方法是newCondition(),返回一个Condition实例。这个方法时返回一个绑定这个Lock实例的条件对象实例。

 

之前使用synchronized的时候,比如生产者和消费者模型中有take和put两个操作,当队列为空时会调用list.wait(),当队列满的时候也会调用list.wait(),就是把当前线程加入到list对象的锁等待池中,而当队列不为空或者队列不是满的时候我们会调用notifyAll或者notify,比如take中调用notify时,它会从锁等待池中随机选一个线程让它进入可运行状态,等待锁释放后去竞争锁,但是这里就有一个问题,其实我们这里需要唤醒的是take线程,但是使用notify的时候随机性很强,很有可能他唤醒的是一个put线程或者别的线程,当然可以使用notifyAll,他会唤醒对象锁池中的所有线程,但是等锁释放后,还是只有一个锁能够竞争到资源进入运行状态,所以这样不能明确快速的指定具体要唤醒的线程。

 

现在jdk5.0提供了Condition,通过lock.newCondition()可以获得绑定当前锁的条件对象,每个条件对象都维护相对于自己这个条件的线程等待池,比如队列非空,可以创建一个Condition not_empty = lock.newCondition();  当take的时候如果队列为空,则not_empty.await(),这样当前线程由这个条件对象来维护,当队列非空的时候就可以通过调用not_empty.sigal()来唤醒那些需要取元素的线程。这样就能把各种线程在不同条件下进行细致分类,灵活操作。不用像之前那样直接用个notifyAll,使用notifyAll把不同条件需求的线程全绑定在一个队列中,一个条件满足就需要唤醒全部线程,然后相互竞争锁,既不精确性能也差。

 

一个简单的生产者和消费者模型实例:

 

Java代码  收藏代码

  1. package com.sxit.test;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5. import java.util.concurrent.locks.Condition;  
  6. import java.util.concurrent.locks.Lock;  
  7. import java.util.concurrent.locks.ReentrantLock;  
  8.   
  9. /** 
  10.  * @功能:使用Lock Conditon 
  11.  * @作者: smile 
  12.  * @时间:2013-4-18 下午5:18:07 
  13.  * @版本:1.0 
  14.  */  
  15. public class Test05 {  
  16.       
  17.     public static Lock lock = new ReentrantLock();;  
  18.     // 容器已满  綁定product線程  
  19.     public static Condition full = lock.newCondition();  
  20.     // 容器为空  綁定consumer線程  
  21.     public static Condition empty = lock.newCondition();  
  22.   
  23.     public static void main(String[] args) {  
  24.         List list = new ArrayList(12);  
  25.         Product product = new Product(list, 10);  
  26.         Consumer consumer = new Consumer(list, 0);  
  27.           
  28.         Thread t1 = new Thread(product);  
  29.         Thread t2 = new Thread(consumer);  
  30.           
  31.         t1.start();  
  32.         t2.start();  
  33.     }  
  34.       
  35.     // 生产  
  36.     static class Product implements Runnable {  
  37.   
  38.         private List list;  
  39.         private int maxCount;  
  40.   
  41.         public Product(List list, int maxCount) {  
  42.             super();  
  43.             this.list = list;  
  44.             this.maxCount = maxCount;  
  45.         }  
  46.   
  47.         @Override  
  48.         public void run() {  
  49.             while(true){  
  50.                 if (lock.tryLock()) {  
  51.                     try {  
  52.                         if (getSize() >= maxCount) {  
  53.                             System.out.println("容器已滿,product線程加入池中...");  
  54.                             full.await();  
  55.                         }  
  56.                         System.out.println("開始生產....");  
  57.                         list.add(new Object());  
  58.                         //喚醒消費者線程  
  59.                         empty.signal();  
  60.                     } catch (InterruptedException e) {  
  61.                         e.printStackTrace();  
  62.                     } finally {  
  63.                         lock.unlock();  
  64.                     }  
  65.                 } else {  
  66.                     System.out.println("未获取生产资格...");  
  67.                 }  
  68.             }  
  69.         }  
  70.   
  71.         public int getSize() {  
  72.             return list.size();  
  73.         }  
  74.     }  
  75.   
  76.     // 消费  
  77.     static class Consumer implements Runnable {  
  78.   
  79.         private List list;  
  80.         private int minCount;  
  81.   
  82.         public Consumer(List list, int minCount) {  
  83.             super();  
  84.             this.list = list;  
  85.             this.minCount = minCount;  
  86.         }  
  87.   
  88.         @Override  
  89.         public void run() {  
  90.             while(true){  
  91.                 if (lock.tryLock()) {  
  92.                     try {  
  93.                         if (getSize() <= minCount) {  
  94.                             System.out.println("容器已空,consumer線程加入池中...");  
  95.                             empty.await();  
  96.                         }  
  97.                         System.out.println("開始消費....");  
  98.                         list.remove(0);  
  99.                         //喚醒生產者線程  
  100.                         full.signal();  
  101.                     } catch (InterruptedException e) {  
  102.                         e.printStackTrace();  
  103.                     } finally {  
  104.                         lock.unlock();  
  105.                     }  
  106.                 } else {  
  107.                     System.out.println("未获取消费资格...");  
  108.                 }  
  109.             }  
  110.         }  
  111.           
  112.         public int getSize() {  
  113.             return list.size();  
  114.         }  
  115.     }  
  116.       
  117. }  

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值