reentrantlock

ReentrantLock分析

匿名 (未验证) 提交于 2019-12-03 00:03:02
主要分析下ReentrantLock锁的占用和释放过程。 AbstractOwnableSynchronizer{ /** * 表示当前占有独占锁的线程,为null时说明锁未被占用 */ private transient Thread exclusiveOwnerThread; } AbstractQueuedSynchronizer extend AbstractOwnableSynchronizer{ private transient volatile Node head;//队列首节点 private transient volatile Node tail;//队列尾节点 private volatile int state;//同步状态,表示锁是否被占用。可重入锁,占用锁时继续获取锁,state=2 } /** * waitStatus: *1:线程取消等待 *-1:后继节点的线程处于等待状态,需要当前结点唤醒 *-2:等待condition,condition.signale()唤醒,该线程会加入到队列中等待获取锁 *-3:下一次共享式同步状态获取将会被无条件地传播下去??没看懂 */ static final class Node { volatile int waitStatus;//当前线程的等待状态。状态被一个线程修改后,立即对其他线程可见 volatile

从ReentrantLock实例分析AbstractQueuedSynchronizer和ConditionObject

匿名 (未验证) 提交于 2019-12-02 23:57:01
1.实例:3个线程交替打印1,2,3一定次数 代码如下: import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class TestReentrantLock { private static final int times = 12; private static int count = 0; public static void main(String[] args) { // 实现1,2,3交替打印times次 Lock lock = new ReentrantLock(); Condition condition1 = lock.newCondition(); Condition condition2 = lock.newCondition(); Condition condition3 = lock.newCondition(); Thread print1 = new Thread(() -> { lock.lock(); for (int i = 0; i < times; i++) { try { while (count % 3 != 0)

简单队列缓存

匿名 (未验证) 提交于 2019-12-02 23:45:01
public enum SequenceEnum { SEQUENCE; SequenceEnum() { } private static final ConcurrentLinkedQueue<String> cache = new ConcurrentLinkedQueue<>(); private static final ReentrantLock lock = new ReentrantLock(); /** * * 出队 */ public String poll() { try { lock.lock(); if (cache.size() < 100) { //必须调用其他方法增加队列数量 offer(SequenceUtil.getSequenceArray()); } } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } return cache.poll(); } /** * * 入队 */ public void offer(String[] sequenceArray) { for (String sequence : sequenceArray) { cache.add(sequence); } } /** * * 队列数量太大,不可使用,因为遍历整个队列

AQS

匿名 (未验证) 提交于 2019-12-02 23:30:02
AbstractQueuedSynchronizer(抽象的队列式的同步器),AQS定义了一套多线程访问共享资源的同步器 框架 ,许多同步类实现都依赖于它,如常用的ReentrantLock/Semaphore/CountDownLatch...。 它维护了一个volatile int state(代表共享资源)和一个FIFO线程等待队列(多线程争用资源被阻塞时会进入此队列)。 state的访问方式有三种: getState() setState() compareAndSetState()   AQS定义两种资源共享方式:Exclusive(独占,只有一个线程能执行,如ReentrantLock)和Share(共享,多个线程可同时执行,如Semaphore/CountDownLatch)。 自定义同步器实现时主要实现以下几种方法: isHeldExclusively():该线程是否正在独占资源。只有用到condition才需要去实现它。 tryAcquire(int):独占方式。尝试获取资源,成功则返回true,失败则返回false。 tryRelease(int):独占方式。尝试释放资源,成功则返回true,失败则返回false。 tryAcquireShared(int):共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。

Java核心技术36讲 - 学习笔记

匿名 (未验证) 提交于 2019-12-02 21:53:52
数据结构 底层实现 线程安全 性能 支持null键值 HashTable 基于哈希表 是 put/get/remove-o(1) 不支持 HashMap 基于哈希表 否 put/get/remove-o(1) 支持 TreeMap 基于红黑树 否 put/get/remove-o(log n) 不支持null键,支持null值 ConcurrentHashMap 锁分段技术 是 并发环境下优于同步版本的集合 不支持 创建型模式,解决对象创建的各种问题,如工厂、单例、构建器(Builder)、原型; 结构型模式,是对软件设计结构的总结,关注于类、对象继承、组合方式的实践经验,如装饰者、外观、组合、适配器、桥接、代理; 行为型模式,是从类和对象之间交互、职责划分等方面总结的模式,如策略、观察者、命令、迭代器、模板方法、访问者。 JDK的IO框架运用了装饰者模式(特征:一系列的类以相同的抽象类或者接口作为其构造函数的入参)。如:InputStream <- FilterInputStream <- BufferedInputStream。 GUI、Swing等的组件事件监听,运用了观察者模式。 新版JDK中HTTP/2 Client API,创建HttpRequest,运用了构建器模式,通常被实现成fluent风格的API,也叫方法链。

Java的Lock同步

匿名 (未验证) 提交于 2019-12-02 21:53:52
  在另一篇文章中 Java的synchronized同步 介绍了使用synchronized实现同步的特性,Java也可以使用Lock实现同步.本文主要介绍了使用Lock类来实现同步,并进行synchronized和Lock之间的比较.   ReentrantLock是一个类,而synchronized是关键字,ReentrantLock实现了Lock接口. public class ReentrantLock implements Lock , java . io . Serializable 把解锁操作放在finally块中是必要的,这保证了锁一定会被释放掉,否则将会造成死锁. ReentrantLock lock = new ReentrantLock (); lock . lock (); try { } finally { lock . unlock (); } 和synchronized一样,Lock锁是可重入的.线程可以重复获得已经持有的锁,锁保持一个持有计数器来跟踪对lock的嵌套调用. 如下的例子,此时线程1可以访问method2(),因为锁是可重入的.但是不能访问method3(),因为持有的是不同的锁. ReentrantLock lock = new ReentrantLock (); ReentrantLock lock1 = new

Java Lock与Condition的理解 ReentrantLock锁的简单使用

匿名 (未验证) 提交于 2019-12-02 21:53:52
Lock ReentrantLock 是我们常用的锁,日常我们都只使用了其中一部分功能如下: ReentrantLock lock = new ReentrantLock (); lock . lock (); try { .... } finally { lock . unlock (); } 实际上Java提供的LinkedBlockingQueue类就是基于ReentrantLock与Condition结合使用的,这是很经典的生产与消费场景,里面有两个锁putLock与takeLock锁。解决问题:取元素时takeLock已经获取到锁了,但是由于列队是空的,使用notEmpty.await()使当前线程处理等待状态,这时如果有新的线程调用take方法时,新的线程也能获取到锁,也会继续等待,当put元素后, notEmpty.signal()发送信号,会唤醒其中一个等待线程。 使用condition可以使线程交互变的更加灵活,ReentrantLock可以定义公平锁与非公平锁,公平锁可以保证线程访问顺序,非公平锁不一定保证线程访问顺序,默认为非公平锁。 //每次取完之后使用自唤醒方法使其它等待线程,多了一重信息通知,取完之后会调用notFull方法唤醒正在等写入的方法 public E take () throws InterruptedException { E x ;

(转)大厂常问到的14个Java面试题

匿名 (未验证) 提交于 2019-12-02 21:52:03
1. synchronized和reentrantlock异同 相同点 都实现了多线程同步和内存可见性语义 都是可重入锁 不同点 实现机制不同 synchronized通过java对象头锁标记和Monitor对象实现 reentrantlock通过CAS、ASQ(AbstractQueuedSynchronizer)和locksupport(用于阻塞和解除阻塞)实现 synchronized依赖jvm内存模型保证包含共享变量的多线程内存可见性 reentrantlock通过ASQ的volatile state保证包含共享变量的多线程内存可见性 使用方式不同 synchronized可以修饰实例方法(锁住实例对象)、静态方法(锁住类对象)、代码块(显示指定锁对象) reentrantlock显示调用trylock()/lock()方法,需要在finally块中释放锁 功能丰富程度不同 reentrantlock提供有限时间等候锁(设置过期时间)、可中断锁(lockInterruptibly)、condition(提供await、signal等方法)等丰富语义 reentrantlock提供公平锁和非公平锁实现 synchronized不可设置等待时间、不可被中断(interrupted) 2. concurrenthashmap为何读不用加锁 jdk1.7 1

[******] java多线程连续打印abc

匿名 (未验证) 提交于 2019-12-02 21:52:03
题目描述 建立三个线程A、B、C,A线程打印10次字母A,B线程打印10次字母B,C线程打印10次字母C,但是要求三个线程同时运行,并且实现交替打印,即按照ABCABCABC的顺序打印。 5种方法 使用synchronized, wait和notifyAll 使用Lock->ReentrantLock 和 state标志 使用Lock->ReentrantLock 和Condition(await 、signal、signalAll) 使用Semaphore 使用AtomicInteger 扩展:采用join实现(一次性打印) 5.1 使用synchronized, wait和notifyAll public class ABC7 { private static Object o = new Object();//所对象 private static int state = 0;//控制顺序 private static int PRINT_NUMBER = 10;//打印次数 private static int THREAD_NUM = 3;//线程数量 static class ThreadGenetic implements Runnable { char name; int data; public ThreadGenetic(char name, int data){

Java锁机制ReentrantLock

匿名 (未验证) 提交于 2019-12-02 21:52:03
ReentrantLock 锁常用于保证程序的人为顺序执行。 写一个类模拟ReentrantLock类的功能 class MyLock{ private boolean lock = false; private int holdCount = 0; private Thread myThread = null; //当前占用锁的线程 public synchronized void lock(){ //线程同步,只允许一个线程来获取这把锁 Thread currThread = Thread.currentThread(); //当前访问线程 if(lock == true && currThread != myThread){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //给予锁 myThread = currThread; lock = true; holdCount ++; } public synchronized void unlock(){ Thread currThread = Thread.currentThread(); //当前访问线程 if(currThread == myThread && holdCount>0){ holdCount -- ; if