ReentrantLock的实现,加上Condition
来源:互联网 发布:木马软件 编辑:程序博客网 时间:2024/06/04 19:55
public class TestLock implement Runnable{ public static ReentrantLock lock = new ReentrantLock(); public static int i = 0; @override public void run(){ for(int j = 0;j < 10000;j++){ lock.lock(); try{ i++; }finally{ lock.unlock(); } } } public static void main(String...args) throws InterruptedException{ TestLock tl = new TestLock(); Thread t1 = new Thread(tl); Thread t2 = new Thread(t2); t1.start(); t2.start(); t1.join(); t2.join(); System.out.print(i); }}
可重入锁使得一个线程连续多次获得同一把锁,但lock()和unlock()的次数要一样。
与synchronized相比,还多了中断线程的功能。即一个线程在等待锁的时候,可以收到一个通知,去中断线程。可以有效避免死锁
jps -l :看哪个java类正在运行,并记录VMID
jstack -l vmid :看堆栈和锁情况
package atalisas.Crawler;import java.util.concurrent.locks.ReentrantLock;/** * Created by 顾文涛 on 2017/8/27. */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; } @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()+":Thread Exit"); } } public static void main(String...args) throws Exception{ 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();//中断一个线程 /* 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 atalisas.Crawler.IntLock.run(IntLock.java:33) at java.lang.Thread.run(Thread.java:745) 13:Thread Exit 12:Thread Exit */ }}
tryLock()的用法
public class TimeLock implements Runnable{ private static ReentrantLock lock = new ReetrantLock(); @override public void run(){ try{ if(lock.tryLock(5,TimeUnit.SECOND)){ Thread.sleep(60000); }else{ System.out.print("get lock failed") } }catch(InterruptedException e){ }finally{ if(lock.isHeldByCurrentThread()) lock.unlock(); } } public static void main(String...args){ TimeLock tl = new TimeLock(); Thread t1 = new Thread(tl); Thread t2 = new Thread(tl); t1.start(); t2.start();//这个会失败 }}
公平锁和非公平锁:公平锁会先来先得,维护一个队列
ReentrantLock lock = new ReentrantLock(true); //通过构造方法实现公平锁
Condition: 与ReentrantLock合用实现等待/通知模式
public class IntLock implements Runnable { public static ReentrantLock lock = new ReentrantLock(); public static Condition condition = lock.newCondition(); @Override public void run() { try{ lock.lock(); condition.await(); System.out.println("Thread is going on!"); }catch (InterruptedException e){} finally { lock.unlock(); } } public static void main(String...args) throws Exception{ IntLock tl = new IntLock(); Thread t1 = new Thread(tl); t1.start(); Thread.sleep(2000); lock.lock(); condition.signalAll(); //过2秒后,通知线程继续运行 lock.unlock(); }}
实现原理
final void lock() { acquire(1);}=>AbstractQueuedSynchronizer.acquirepublic final void acquire(int arg) { if (!tryAcquire(arg) && //首先尝试获取,未获取则入队列,获取直接返回不打断 acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) //addWaiter,将新请求加入队列尾进行等待,tryAcquire子类实现 selfInterrupt(); //Thread.currentThread().interrupt();}=>ReentrantLock.FairSync.tryAcquireprotected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); //获取当前线程 int c = getState(); //获取父类AQS中的标志位 if (c == 0) { if (!hasQueuedPredecessors() && //如果队列中没有其他线程,说明没有线程占有锁 compareAndSetState(0, acquires)) { //修改一下状态位,acquires为1 setExclusiveOwnerThread(current); //如果通过CAS操作将状态更新成功,则证明当前线程得锁,并做一个标记 return true; //表示tryAcquire成功 } } else if (current == getExclusiveOwnerThread()) { //如果不为0,则锁被拿走,但是为可重入锁,要判断是不是自己拿的 int nextc = c + acquires; //将lock()的次数变为n+1次,说明也要unlock这么多次 if (nextc < 0) throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false;}=>AbstractQueuedSynchronizer.AddWaiterprivate Node addWaiter(Node mode) { Node node = new Node(Thread.currentThread(), mode); //用当前线程构建一个Node,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)) { //修改失败,表示有并发,进入enq(node)死循环 pred.next = node; return node; } } enq(node); //进入死循环 return node;}=>AbstractQueuedSynchronizer.enqprivate Node enq(final Node node) { for (;;) { //死循环,为了避免竞态失败 Node t = tail; if (t == null) { // Must initialize //队列尾为空 if (compareAndSetHead(new Node())) //如果无竞态 tail = head; //尾等于头,说明只有一个节点 } else { node.prev = t; // if (compareAndSetTail(t, node)) { //不为空则将入队列尾 t.next = node; return t; //无竞态则成功 } } }}=>AbstractQueuedSynchronizer.acquireQueuedfinal 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)) { //如果当前的节点是head说明他是队列中第一个“有效的”节点,因此尝试获取,上文中有提到这个类是交给子类去扩展的。 setHead(node);//成功后,将上图中的黄色节点移除,Node1变成头节点。 p.next = null; // help GC failed = false; return interrupted; } if (shouldParkAfterFailedAcquire(p, node) && //否则,检查前一个节点的状态为,看当前获取锁失败的线程是否需要挂起。 parkAndCheckInterrupt()) //如果需要,借助JUC包下的LockSopport类的静态方法Park挂起当前线程。知道被唤醒。 interrupted = true; } } finally { if (failed) //如果有异常 cancelAcquire(node);// 取消请求,对应到队列操作,就是将当前节点从队列中移除。 }}
阅读全文
0 0
- ReentrantLock的实现,加上Condition
- 利用ReentrantLock的Condition实现线程之间的通信
- ReentrantLock 和 Condition的使用
- java 使用ReentrantLock Condition实现阻塞队列
- ReentrantLock使用Condition实现通知部分线程
- ReentrantLock使用Condition实现通知部分线程
- 线程锁ReentrantLock和Condition的使用
- 多线程锁的使用(ReentrantLock/Condition/ReentrantReadWriteLock)
- ReentrantLock类和Condition类的使用
- ReentrantLock(二):正确使用Condition实现等待与通知
- 使用ReentrantLock和Condition实现生产者消费者模型
- ReenTrantLock与Condition
- ReentrantLock Condition 用法
- ReentrantLock与Condition
- ReentrantLock Condition使用详解
- ReentrantLock与Condition
- ReentrantLock与Condition
- synchronized, reentrantlock,condition
- Apache与Nginx的优缺点比较
- AngualrJs 最新 文件图片上传教程6:Server-config
- Android中使用Opencv自带JavaCameraView实现高帧率竖屏显示
- 使用某个用户登录命令:kinit adminad
- PopupWindow使用
- ReentrantLock的实现,加上Condition
- tf.Variable()与tf.get_variable()与不同之处
- Android跳转-ARouter详细使用教程
- 多线程以及线程同步
- js各种小功能大合集
- Unity 防止屏保问题
- Mac下安装SecureCRT客户端
- LeetCode
- VLOOKUP 函数