ReentrantLock重入锁
来源:互联网 发布:狩猎波尔卡 知乎 编辑:程序博客网 时间:2024/05/01 16:33
1使用案例
public class ReenterLock implements Runnable{ public static ReentrantLock lock=new ReentrantLock(); public static int i=0; @Override public void run() { for (int j = 0; j <100; j++) { lock.lock(); try{ i++; System.out.println(Thread.currentThread().getName()+" "+i); }finally { lock.unlock(); } } } public static void main(String[] args)throws InterruptedException{ ReenterLock r1=new ReenterLock(); Thread t1=new Thread(r1); Thread t2=new Thread(r1); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(i); }}
Thread-0 1Thread-0 2Thread-0 3Thread-0 4Thread-0 5Thread-0 6Thread-0 7Thread-0 8Thread-0 9Thread-0 10Thread-0 11Thread-0 12Thread-0 13Thread-0 14Thread-0 15Thread-0 16Thread-0 17Thread-0 18Thread-0 19Thread-0 20Thread-0 21Thread-0 22Thread-0 23Thread-0 24Thread-0 25Thread-0 26Thread-0 27Thread-0 28Thread-0 29Thread-0 30Thread-0 31Thread-0 32Thread-0 33Thread-0 34Thread-0 35Thread-0 36Thread-0 37Thread-0 38Thread-0 39Thread-0 40Thread-0 41Thread-0 42Thread-0 43Thread-0 44Thread-0 45Thread-0 46Thread-0 47Thread-0 48Thread-0 49Thread-0 50Thread-0 51Thread-0 52Thread-0 53Thread-0 54Thread-0 55Thread-0 56Thread-0 57Thread-0 58Thread-0 59Thread-0 60Thread-0 61Thread-0 62Thread-0 63Thread-0 64Thread-0 65Thread-0 66Thread-0 67Thread-0 68Thread-0 69Thread-0 70Thread-0 71Thread-0 72Thread-0 73Thread-0 74Thread-0 75Thread-0 76Thread-0 77Thread-0 78Thread-0 79Thread-0 80Thread-0 81Thread-0 82Thread-0 83Thread-0 84Thread-0 85Thread-0 86Thread-0 87Thread-0 88Thread-0 89Thread-0 90Thread-0 91Thread-0 92Thread-0 93Thread-0 94Thread-0 95Thread-0 96Thread-0 97Thread-0 98Thread-0 99Thread-0 100Thread-1 101Thread-1 102Thread-1 103Thread-1 104Thread-1 105Thread-1 106Thread-1 107Thread-1 108Thread-1 109Thread-1 110Thread-1 111Thread-1 112Thread-1 113Thread-1 114Thread-1 115Thread-1 116Thread-1 117Thread-1 118Thread-1 119Thread-1 120Thread-1 121Thread-1 122Thread-1 123Thread-1 124Thread-1 125Thread-1 126Thread-1 127Thread-1 128Thread-1 129Thread-1 130Thread-1 131Thread-1 132Thread-1 133Thread-1 134Thread-1 135Thread-1 136Thread-1 137Thread-1 138Thread-1 139Thread-1 140Thread-1 141Thread-1 142Thread-1 143Thread-1 144Thread-1 145Thread-1 146Thread-1 147Thread-1 148Thread-1 149Thread-1 150Thread-1 151Thread-1 152Thread-1 153Thread-1 154Thread-1 155Thread-1 156Thread-1 157Thread-1 158Thread-1 159Thread-1 160Thread-1 161Thread-1 162Thread-1 163Thread-1 164Thread-1 165Thread-1 166Thread-1 167Thread-1 168Thread-1 169Thread-1 170Thread-1 171Thread-1 172Thread-1 173Thread-1 174Thread-1 175Thread-1 176Thread-1 177Thread-1 178Thread-1 179Thread-1 180Thread-1 181Thread-1 182Thread-1 183Thread-1 184Thread-1 185Thread-1 186Thread-1 187Thread-1 188Thread-1 189Thread-1 190Thread-1 191Thread-1 192Thread-1 193Thread-1 194Thread-1 195Thread-1 196Thread-1 197Thread-1 198Thread-1 199Thread-1 200200
// lock.unlock();
屏蔽 lock.unlock()这行代码的打印结果,加锁后必须释放锁,否则其他线程无法获取资源
Thread-0 1Thread-0 2Thread-0 3Thread-0 4Thread-0 5Thread-0 6Thread-0 7Thread-0 8Thread-0 9Thread-0 10Thread-0 11Thread-0 12Thread-0 13Thread-0 14Thread-0 15Thread-0 16Thread-0 17Thread-0 18Thread-0 19Thread-0 20Thread-0 21Thread-0 22Thread-0 23Thread-0 24Thread-0 25Thread-0 26Thread-0 27Thread-0 28Thread-0 29Thread-0 30Thread-0 31Thread-0 32Thread-0 33Thread-0 34Thread-0 35Thread-0 36Thread-0 37Thread-0 38Thread-0 39Thread-0 40Thread-0 41Thread-0 42Thread-0 43Thread-0 44Thread-0 45Thread-0 46Thread-0 47Thread-0 48Thread-0 49Thread-0 50Thread-0 51Thread-0 52Thread-0 53Thread-0 54Thread-0 55Thread-0 56Thread-0 57Thread-0 58Thread-0 59Thread-0 60Thread-0 61Thread-0 62Thread-0 63Thread-0 64Thread-0 65Thread-0 66Thread-0 67Thread-0 68Thread-0 69Thread-0 70Thread-0 71Thread-0 72Thread-0 73Thread-0 74Thread-0 75Thread-0 76Thread-0 77Thread-0 78Thread-0 79Thread-0 80Thread-0 81Thread-0 82Thread-0 83Thread-0 84Thread-0 85Thread-0 86Thread-0 87Thread-0 88Thread-0 89Thread-0 90Thread-0 91Thread-0 92Thread-0 93Thread-0 94Thread-0 95Thread-0 96Thread-0 97Thread-0 98Thread-0 99Thread-0 100
有显示的操作过程,必须显示指定何时加锁,何时释放锁。加锁后必须释放锁。
2重入含义
ReentrantLock是可以反复进入的,反复仅仅限于一个线程。一个线程连续两次获得同一把锁是允许的,如果不允许这种操作,线程在第二次申请锁的时候会和自己发生死锁。一个线程加多少次锁,必须释放多少次锁,如果释放的次数少,相当于线程还持有这个锁,其他线程无法
获取资源。
lock.lock(); lock.lock(); try{ i++; System.out.println(Thread.currentThread().getName()+" "+i); }finally { lock.unlock(); lock.unlock();
3可中断的锁
对于synchronized来说,一个线程在等待锁,结果要么是获得锁,要么就是保持等待的状态。使用重入锁,线程在等待的过程中,程序可以根据需要取消对锁的请求。这对于处理死锁有一定帮助。
public class IntLock implements Runnable{ @Override public 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 ReentrantLock lock1=new ReentrantLock(); public static ReentrantLock lock2=new ReentrantLock(); int lock; public IntLock(int lock){ this.lock=lock; } public static void main(String[] args)throws InterruptedException{ IntLock r1=new IntLock(1); IntLock r2=new IntLock(2); Thread t1=new Thread(r1); Thread t2=new Thread(r2); t1.start(); t2.start(); Thread.sleep(1000); t2.interrupt(); }}
执行结果:
10:线程退出
9:线程退出
java.lang.InterruptedException
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
at IntLock.run(IntLock.java:22)
at java.lang.Thread.run(Thread.java:745)
Process finished with exit code 0
线程t1和t2启动后,t1先占用lock1,再占用lock2,t2先占用lock2,再占用lock1,lock.lockInterruptibly()是一个可以对中断进行响应的锁操作,即在锁的等待过程中可以响应中断。两个线程都在等待对方释放锁,两个线程处于死锁状态,执行 t2.interrupt()操作后,t2线程被中断,t2会放弃对lock1的申请,同时释放lock2,线程t1获得lock2锁,继续执行,最后两个线程都退出,t1真正完成工作,t2线程放弃任务直接退出释放资源。
4tryLock()/tryLock(long time,TimeUnit unpublic 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("get lock failed"); } }catch (InterruptedException e){ e.printStackTrace(); }finally{ if(lock.isHeldByCurrentThread())lock.unlock(); }}public static void main(String[] args){ TimeLock t1=new TimeLock(); Thread th1=new Thread(t1); Thread th2=new Thread(t1); th1.start(); th2.start();}
}
如果超过5秒没有得到锁就会返回false,占用锁的线程持用锁的时间长达6秒,因此另外一个线程无法在5秒的等待时间内获得锁。
锁在大多数情况下,锁的申请都是非公平的,系统会随机地从锁的等待队列中挑选一个。公平的锁会按时间先后顺序,保证先到者先得后到者后得。公平锁的一大特点是:不会产生饥饿。在使用synchronized关键字进行锁控制时,产生的锁是非公平的。
公平锁的创建:
public ReentrantLock(boolean fair)
ReentrantLock lock=new ReentrantLock(true);
实现公平锁必然要维护一个有序队列,因此公平锁的实现成本比较高,性能相对也非常低,默认情况下,锁是非公平的。
public class FairLock implements Runnable { public static ReentrantLock fairLock = new ReentrantLock(true); @Override public void run() { while (true) { try { fairLock.lock(); System.out.println(Thread.currentThread().getName() + "获得锁"); } finally { fairLock.unlock(); } } } public static void main(String[] args) { FairLock r1 = new FairLock(); Thread t1 = new Thread(r1, "Thread_t1"); Thread t2 = new Thread(r1, "Thread_t2"); t1.start(); t2.start(); }}
结果:t1 t2交替获得锁Thread_t2获得锁Thread_t1获得锁Thread_t2获得锁Thread_t1获得锁Thread_t2获得锁Thread_t1获得锁Thread_t2获得锁Thread_t1获得锁Thread_t2获得锁
Reentrantlock重要方法整理
lock():获得锁,如果锁被占用,则等待
lockInterruptibly():获得锁,但优先响应中断
tryLock():尝试获得锁,如果成功返回true,失败则返回false。该方法不等待,立即返回。
tryLock(long time,TimeUnit unit):在给定时间内尝试获得锁
unlock():释放锁
重入锁的实现要素:
1原子状态:原子状态使用CAS操作来存储当前锁的状态,判断锁是否已经被别的线程持有。
2等待队列:所有没请求到锁的线程,会进入等待队列等待。待有线程释放锁,系统就能从等待队列中唤醒一个线程,继续工作。
3阻塞原语park()和unpark(),用来挂起和恢复线程。没有得到锁的线程将会被挂起。
- 重入锁--ReentrantLock
- 重入锁--ReentrantLock
- 重入锁ReentrantLock
- 重入锁ReentrantLock
- 重入锁--ReentrantLock
- 重入锁--ReentrantLock
- ReentrantLock 重入锁
- 重入锁ReentrantLock
- ReentrantLock重入锁
- 重入锁--ReentrantLock
- 重入锁ReentrantLock
- ReentrantLock重入锁
- ReentrantLock重入锁
- ReentrantLock(重入锁)以及公平性
- ReentrantLock(重入锁)以及公平性
- ReentrantLock(重入锁)以及公平性
- ReentrantLock(重入锁)以及公平性
- Java重入锁ReentrantLock
- 使用Topshelf创建Windows服务
- ubuntu 中的 C 环境的 头文件 和 库
- 简单的Python登录小程序
- Java ConcurrentHashMap(JDK8)的实现原理
- 将json转发到网页时乱码的解决
- ReentrantLock重入锁
- Chapter01 流与文件(一) 流
- 【C语言】字符串
- [C++标准模板库:自修教程与参考手册]关于deque
- Struts2(十五):解决表单的重复提交
- boot repair
- ubuntu 系统的一些操作
- Python基础03 序列
- 基于Zookeeper的Hadoop HA实现