ConCurrent并发包 - Lock详解(转)

Posted panxuejun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ConCurrent并发包 - Lock详解(转)相关的知识,希望对你有一定的参考价值。

synchronized的缺陷

 
我们知道,可以利用synchronized关键字来实现共享资源的互斥访问。Java 5在java.util.concurrent.locks包下提供了另一种来实现线程的同步访问,那就是Lock。既然有了synchronized来实现线程同步,Java为什么还需要提供Lock呢?
synchronized是Java的一个关键字,当我们使用synchronized来修饰方法或代码块时,线程必须先获得对应的锁才能执行该段代码。而其他线程只能一直等待,直到当前线程释放锁并获得对应的锁才能进入该段代码。这里获取锁的线程释放锁只会有两种情况:
  • 获取锁的线程执行完该段代码,线程会释放占有的锁;
  • 线程执行发生异常,此时JVM会让线程自动释放锁。
那么如果这个占有锁的线程由于等待IO或其他原因(比如调用sleep方法)被阻塞,但是还没有释放锁,那么其他线程只能干巴巴的等着,试想这多么影响程序的执行效率。
当多个线程同时读写文件是,我们知道读操作和写操作会发生冲突,写操作和写操作也会发生冲突,但是读操作和读操作之间不会冲突。synchronized关键字对一段代码加锁,所有的线程必须先获得对应的锁才有该代码段的执行权限。如果多个线程同时进行读操作时,使用synchronized关键字会导致在任何时刻只有一个线程读,其他线程等待,大大降低执行效率。
 
Lock可以对以上种种情况作优化,提供更好的执行效率。另外,Lock方便了对锁的管理,可以自由的加锁和释放锁,还可以判断有没有成功获取锁。但是在使用Lock时要注意,Lock需要开发者手动去释放锁,如果没有主动释放锁,就要可能导致死锁出现。建议在finally语句块中释放Lock锁。
 
 

concurrent.locks包下常用类

 
1. Lock
 
首先要说明的是Lock,它是一个接口:
[java] view plain copy
 
  1. public interface Lock {  
  2.     void lock();  
  3.     void lockInterruptibly() throws InterruptedException;  
  4.     boolean tryLock();  
  5.     boolean tryLock(long time, TimeUnit unit) throws InterruptedException;  
  6.     void unlock();  
  7.     Condition newCondition();  
  8. }  
  • lock()方法用来获取锁。
  • tryLock()尝试获取锁,如果成功则返回true,失败返回false(其他线程已占有锁)。这个方法会立即返回,在拿不到锁时也不会等待。
  • tryLock(long time, TimeUnit unit)方法和tryLock()方法类似,只不过在拿不到锁时等待一定的时间,如果超过等待时间还拿不到锁就返回false。
  • lockInterruptibly()方法比较特殊,当通过这个方法获取锁时,如果该线程正在等待获取锁,则它能够响应中断。也就是说,当两个线程同时通过lockInterruptibly()获取某个锁时,假如线程A获得了锁,而线程B仍在等待获取锁,那么对线程B调用interrupt()方法可以中断B的等待过程。
[java] view plain copy
 
  1. // lock()的使用  
  2. Lock lock = ...;  
  3. lock.lock();  
  4. try{  
  5.     //处理任务  
  6. }catch(Exception ex){  
  7.        
  8. }finally{  
  9.     lock.unlock();   //释放锁  
  10. }  
[java] view plain copy
 
  1. // tryLock()的使用  
  2. Lock lock = ...;  
  3. if(lock.tryLock()) {  
  4.      try{  
  5.          //处理任务  
  6.      }catch(Exception ex){  
  7.            
  8.      }finally{  
  9.          lock.unlock();   //释放锁  
  10.      }   
  11. }else {  
  12.     //如果不能获取锁,则直接做其他事情  
  13. }  
[java] view plain copy
 
  1. // lockInterruptibly()的使用  
  2. public void method() throws InterruptedException {  
  3.     lock.lockInterruptibly();  
  4.     try {    
  5.      //.....  
  6.     }  
  7.     finally {  
  8.         lock.unlock();  
  9.     }    
  10. }  
使用synchronized关键字,当线程处于等待锁的状态时,是无法被中断的,只能一直等待。

以上是关于ConCurrent并发包 - Lock详解(转)的主要内容,如果未能解决你的问题,请参考以下文章

java基础Java并发包

Java高并发--------JDK并发包-------3

Java高并发--------JDK并发包-------3

java并发包java.util.concurrent详解

举例详解 java.util.concurrent 并发包 4 种常见类

举例详解 java.util.concurrent 并发包 4 种常见类