Java 锁 重入锁 读写锁
来源:互联网 发布:图像特征检测算法 编辑:程序博客网 时间:2024/05/04 10:05
ReentrantLock锁
java5.0之前,我们对于共享对象访问的机制只有synchronized关键字和volatile变量,现在提供了ReentrantLock
该锁比synchronized更多的灵活处置,比如,synchronized没法去解决死锁,不能中断正在等待获取锁的线程.
ReentrantLock锁
1.可重入
单线程可以重复进入,但必须重复退出。
2.可中断
可以中断正在等待的线程
3可限时
超时不能获得锁,就返回false,不会永久等待构成死锁
4.可轮训
tryLock() ,只有在获取到锁时,才返回true.
可轮训和可限时可以规避死锁
5.公平锁
public ReentrantLock(boolean fair)
public static ReentrantLock fairLock = new ReentrantLock(true);
设置为true时,按照先来先得的原则,后来的被放进等待队列中.
那么怎么选择synchronized和ReentrantLock了
从上面可以看出,ReentrantLock有很多的特性,那么如果想选择可中断,可限时,可轮询等就可以选择ReentrantLock.
锁的书写方式:
class X { private final ReentrantLock lock = new ReentrantLock(); // ... public void m() { lock.lock(); // block until condition holds try { // ... method body } finally { lock.unlock() } } }
2. 可重入代码如下:
public class TestReentrantLock implements Runnable {private ReentrantLock lock = new ReentrantLock();private int a;@Overridepublic void run() {// TODO Auto-generated method stubfor (int i = 0; i < 1000; i++) {try {// 加锁lock.lock();a++;} catch (Exception e) {// TODO: handle exception} finally {// 释放锁lock.unlock();}}}public static void main(String[] args) throws InterruptedException {TestReentrantLock tr = new TestReentrantLock();Thread t1 = new Thread(tr);Thread t2 = new Thread(tr);t1.start();t2.start();t1.join();t2.join();System.out.println(tr.a);}}
3.可限时
如果在规定的时间内范围内,没有获取到该锁,等返回false,等待.
/** * 一段时间内,尝试获取锁 * @author Administrator * */public class TimeReentrantLock implements Runnable{private ReentrantLock lock = new ReentrantLock();@Overridepublic void run() {// TODO Auto-generated method stubtry {//设置在5秒内获取锁if(lock.tryLock(5, TimeUnit.SECONDS)){System.out.println(Thread.currentThread().getName()+"获取锁成功");Thread.sleep(6000);}else{System.out.println(Thread.currentThread().getName()+"获取锁失败");}} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{if(lock.isHeldByCurrentThread()){lock.unlock();}}}public static void main(String[] args) {TimeReentrantLock tr = new TimeReentrantLock();Thread t1 = new Thread(tr,"t1");Thread t2 = new Thread(tr,"t2");t1.start();t2.start();}}
结果:
t1获取锁成功
t2获取锁失败
Exception in thread "t2" java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(Unknown Source)
at java.util.concurrent.locks.ReentrantLock.unlock(Unknown Source)
at com.study.displaylock.TimeReentrantLock.run(TimeReentrantLock.java:25)
at java.lang.Thread.run(Unknown Source)
ReentrantLock源码分析
前面我们看到,ReentrantLock有两种锁,一种是公平锁,一种是非公平锁。
首先,来学习不公平锁
主要是下面三种技术来实现:
1.cas 2.等待队列 3.park
不公锁调用如下:
final void lock() { if (compareAndSetState(0, 1))//使用cas尝试设置值,如果设置成功,则表明现在没有现成得到锁,那么获取成功 setExclusiveOwnerThread(Thread.currentThread()); else acquire(1);//再次尝试 } public final void acquire(int arg) { if (!tryAcquire(arg) && //再次尝试获取锁,成功则不再做如下操作 acquireQueued(addWaiter(Node.EXCLUSIVE), arg))//否则添加到等待队列中 selfInterrupt(); }private Node addWaiter(Node mode) { Node node = new Node(Thread.currentThread(), mode); // Try the fast path of enq; backup to full enq on failure Node pred = tail; if (pred != null) { node.prev = pred; if (compareAndSetTail(pred, node)) {//cas成功,则直接放入队列 pred.next = node; return node; } } enq(node);.//不成功,强制放入队列 return node; }final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { boolean interrupted = false; for (;;) { final Node p = node.predecessor(); if (p == head && tryAcquire(arg)) {//再次尝试加锁 setHead(node); p.next = null; // help GC failed = false; return interrupted; } if (shouldParkAfterFailedAcquire(p, node) &&//如果等待状态singal的就直接返回,singal表示这个线程可以unpack,如果是cancelled,则忽略这些线程 parkAndCheckInterrupt())//否则,pack这些线程 interrupted = true; } } finally { if (failed) cancelAcquire(node); } }
释放锁
public void unlock() { sync.release(1); }public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h);//unpark 释放这些线程 return true; } return false; }
读写锁:
ReentrantLock不管是读取还是写入都是互斥的,这对于大量的并发读取操作来说,性能就不会太高,ReentrantReadWriteLock读写锁,可以允许多个线程来读,只有一个线程来写。
它是读读不互斥,读写互斥,写写互斥。
/** * 读写锁 * 读写互斥 写写互斥 读读不互斥 * */public class TestReentrantRWLock {private ReentrantReadWriteLock rw = new ReentrantReadWriteLock();private ReadLock rl = rw.readLock();private WriteLock wl = rw.writeLock();private int i=5;public void get(){try {rl.lock();Thread.sleep(2000);System.out.println("i的值是"+i);rl.unlock();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public void add(){try {wl.lock();i++;System.out.println("i++后的值是:"+i);Thread.sleep(2000);wl.unlock();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public static void main(String[] args) {final TestReentrantRWLock trl = new TestReentrantRWLock(); Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubtrl.get();}}); Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubtrl.get();}}); Thread t3 = new Thread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubtrl.add();}}); //t1.start(); t3.start(); t2.start();}}
阅读全文
0 0
- Java 锁 重入锁 读写锁
- Java读写锁
- Java读写锁
- java中的读写锁
- Java读写锁问题
- java 线程读写锁
- java 读写锁
- java 读写锁 ReadWriteLock
- java中的读写锁
- java读写锁
- Java多线程--读写锁
- Java读写锁ReadWriteLock
- java读写锁深入
- java读写锁实现机制
- Java读写锁的代码
- Java读写锁的使用
- Java中读写锁ReadWriteLock
- 【Java多线程】-读写锁ReadWriteLock
- LeetCode刷题(C++)——Linked List Cycle II(Medium)
- 关于matlab高效管理内存的方法,进而降低Out of Memory出现的机率
- 在头文件还是源文件中使用extern
- ES6
- 软考----网络
- Java 锁 重入锁 读写锁
- leetcode_Count and Say
- 到底如何区分什么是架构、框架、模式和平台 ?
- 欢迎使用CSDN-markdown编辑器
- Webpack-源码四,从源码分析如何写一个loader
- RecyclerView异步加载图片乱序问题
- 传统企业码农如何跳槽互联网
- jQuery 层次选择器
- std::map 自定义类做为key时 find operator< 的正确写法