《并发编程》--10.重入锁

来源:互联网 发布:mysql 最小id 查询 编辑:程序博客网 时间:2024/05/21 10:11

在jdk5的时代,重入锁可以完全替代synchronized。但从jdk6开始对synchronized做了大量的优化,使两者在性能上差距不大。

以下是冲入锁的一段简单代码

public class ReenterLock implements Runnable {public static ReentrantLock lock = new ReentrantLock();public static int i  = 0;@Overridepublic void run() {for(int j = 0;j<1000000;j++){lock.lock();  //加锁try {i++;}finally{lock.unlock(); //释放锁} }}public static void main(String[] args) throws InterruptedException {ReenterLock ti = new ReenterLock();Thread t1 = new Thread(ti);Thread t2 = new Thread(ti);t1.start();t2.start();t1.join();t2.join();System.out.println(i);}}


从代码中可以看出:和synchronized相比,重入锁有着明显的操作过程,研发人员必须手动操作,合适加锁,合适释放锁。冲入锁对逻辑控制灵活性远远高于synchronized。

但是有一点必须注意:退出时必须释放锁,否则其他线程将无法继续访问临界区。,

重入锁对单线程是可以反复进入的,并不支持多线程,如下 例子,只修改run方法

@Overridepublic void run() {for(int j = 0;j<1000000;j++){lock.lock();  //加锁lock.lock();  //加锁try {i++;}finally{lock.unlock(); //释放锁lock.unlock(); //释放锁} }}

同一线程在第二次获得锁时,将会和自己产生死锁。反之,释放锁的次数少了,那么相当于其他线程继续持有这个锁,其他线程将无法进入临界区。


1.中断响应

对于synchronized来说,如果一个线程在等待所,只有两个情况,要么持有锁继续执行,要不在持续等待中。

而对于重入锁来说:还多了另一种选择,等等待过程中,取消锁的等待。这种情况对于处理死锁有一定帮助。代码如下

public class IntLock implements Runnable{public static ReentrantLock lock1 = new ReentrantLock();public static ReentrantLock lock2 = new ReentrantLock();int lock ;/** * 控制加锁顺序,方便构成死锁 */public IntLock(int lock){this.lock = lock;}@Overridepublic void run() {try {if(lock ==1){lock1.lockInterruptibly();try {Thread.sleep(500);} catch (InterruptedException e) {lock2.lockInterruptibly();}}else{lock2.lockInterruptibly();try {Thread.sleep(500);} catch (InterruptedException e) {lock1.lockInterruptibly();}}} catch (InterruptedException e) {e.printStackTrace();}finally {if(lock1.isHeldByCurrentThread());{lock1.unlock();}if(lock2.isHeldByCurrentThread());{lock2.unlock();}System.out.println(Thread.currentThread().getId()+" : 线程退出 ");}}public static void main(String[] args)throws InterruptedException{IntLock i1 = new IntLock(1);IntLock i2 = new IntLock(2);Thread t1 = new Thread(i1);Thread t2 = new Thread(i2);t1.start();t2.start();Thread.sleep(1000);t2.interrupt();//中断其中一个线程}}

2.锁申请等待限时

tryLock()方法接受两个参数,第1个表示等待时长,第二个表示计量单位。

表示在等这个锁的请求中,最多等待2秒,如果超过2秒没有获得锁,将返回false。代码如下

public class TimeLock implements Runnable{public static ReentrantLock lock = new ReentrantLock();@Overridepublic void run() {try{if(lock.tryLock(5,TimeUnit.SECONDS)){//第一个表示等待时长,第二个表示计量单位Thread.sleep(6000);}else{System.out.println("获得所失败!!!");}}catch(InterruptedException e){e.printStackTrace();}finally {if (lock.isHeldByCurrentThread()) lock.unlock();}}public static void main(String[] args)throws InterruptedException{TimeLock i1 = new TimeLock();Thread t1 = new Thread(i1);Thread t2 = new Thread(i1);t1.start();t2.start();}}

ReentrantLock的重要方法整理

1.lock():获得锁,如果所已经被占用,等待

2.lock.lockInterruptibly( );:获得所,有限响应中断

3.tryLock():尝试获得所,成功返回true,失败返回false。该方法不等待

4.lock.tryLock(5,TimeUnit.SECONDS):在指定时间获得所

5.unlock():释放锁



原创粉丝点击