reentrantlock

同步锁——ReentrantLock

╄→гoц情女王★ 提交于 2020-02-25 22:37:36
本博客系列是学习并发编程过程中的记录总结。由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅。 并发编程系列博客传送门 Lock接口简介 热血小说 www.v1122.com 在JUC包下面有一个 java.util.concurrent.locks 包,这个包提供了一系列基础的锁工具,对传统的synchronizd、wait和notify等同步机制进行补充和增强。下面先来介绍下这个Lock接口。 Lock 接口可以视为 synchronized 的增强版,提供了更灵活的功能。相对于 synchronized , Lock 接口还提供了限时锁等待、锁中断和锁尝试等功能。该接口的定义如下 public interface Lock { // 尝试去获得锁 // 如果锁不可用,当前线程会变得不可用,直到获得锁为止。(中途会忽略中断) void lock(); // 尝试去获取锁,如果锁获取不到,线程将不可用 // 知道获取锁,或者被其他线程中断 // 线程在获取锁操作中,被其他线程中断,则会抛出InterruptedException异常,并且将中断标识清除。 void lockInterruptibly() throws InterruptedException; // 锁空闲时返回true,锁不空闲是返回false boolean tryLock(); //

同步锁——ReentrantLock

和自甴很熟 提交于 2020-02-25 12:00:38
本博客系列是学习并发编程过程中的记录总结。由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅。 并发编程系列博客传送门 Lock接口简介 在JUC包下面有一个 java.util.concurrent.locks 包,这个包提供了一系列基础的锁工具,对传统的synchronizd、wait和notify等同步机制进行补充和增强。下面先来介绍下这个Lock接口。 Lock 接口可以视为 synchronized 的增强版,提供了更灵活的功能。相对于 synchronized , Lock 接口还提供了限时锁等待、锁中断和锁尝试等功能。该接口的定义如下 public interface Lock { // 尝试去获得锁 // 如果锁不可用,当前线程会变得不可用,直到获得锁为止。(中途会忽略中断) void lock(); // 尝试去获取锁,如果锁获取不到,线程将不可用 // 知道获取锁,或者被其他线程中断 // 线程在获取锁操作中,被其他线程中断,则会抛出InterruptedException异常,并且将中断标识清除。 void lockInterruptibly() throws InterruptedException; // 锁空闲时返回true,锁不空闲是返回false boolean tryLock(); // 在unit时间内成功获取锁

LinkedBlockingQueue学习笔记

荒凉一梦 提交于 2020-02-24 01:31:53
今天剖析学习了LinkedBlockingQueue,总结下笔记 我们从类注释上大概可以得到如下信息: 1.基于链表的阻塞队列,其底层的数据结构是链表; 2.链表维护先入先出队列,新元素被放在队尾,获取元素从队头部拿; 3.链表大小在初始化的时候可以设置,默认是 Integer 的最大值; 4.可以使用 Collection 和 Iterator 两个接口的所有操作,因为实现了两者的接口。 LinkedBlockingQueue 内部构成简单来说,分成三个部分:链表存储 + 锁 + 迭代器,我们来看下源码。 static class Node < E > { E item ; /** * One of: * - the real successor Node * - this Node, meaning the successor is head.next * - null, meaning there is no successor (this is the last node) */ Node < E > next ; Node ( E x ) { item = x ; } } /** The capacity bound, or Integer.MAX_VALUE if none */ private final int capacity ; /** Current

Java-多线程

为君一笑 提交于 2020-02-22 17:22:44
概念 进程具有自己变量的完备集;线程则共享相同的数据。 抢占式调度:直接中断而不需要实现和 被中断程序 协商 协作式调度:只有在被中断程序同意交出控制权之后才能执行中断 多线程实现 方法一: class MyRunnable implements Runnable { public void run() { ... } } Runnable r = new MyRunnable(); Thread t = new Thread(r); t.start(); 方法二(不建议): class MyThread extends Thread { public void run() { ... } } Thread t = new MyThread(); t.start(); Thread类 sleep(t):static|线程暂停t毫秒,暂停当前线程的活动,会抛出 InterruptedException void run() void start() static Thread currentThread():返回代表当前执行线程的Thread对象 void interrupt():发送中断请求给一个线程,中断状态为true,如果线程当前被sleep调用阻塞,则抛出InterruptedException boolean isInterrupted(): 检查线程是否被终止

并发编程之第四篇

房东的猫 提交于 2020-02-15 10:19:07
并发编程之第四篇 4.11 多把锁 4.12 活跃性 饥饿 4.13 ReentrantLock 同步模式之顺序控制 交替输出 4.11 多把锁 一间大屋子有两个功能 : 睡觉、学习、互不相干 现在小南要学习,小女要睡觉,但如果只用一间屋子(一个对象锁)的话,那么并发度很低 解决方法时准备多个房间(多个对象锁) 4.12 活跃性 死锁 有这样的情况 : 一个线程需要同时获取多把锁,这时就容易发生死锁 t1 线程获得A对象锁,接下来想获取B对象的锁 t2 线程获取B对象锁,接下来想获取A对象的锁 定位死锁 检测死锁可以使用jconsole工具,或者使用jps定位进程id,再用jstack定位死锁 : 饥饿 先来看看一个线程饥饿的例子,使用顺序加锁的方式解决之前的死锁问题 顺序加锁的解决方案 4.13 ReentrantLock 相对于synchronized它具备如下特点 可中断 可设置超时时间 可以设置为公平锁 支持多个条件变量 与synch一样,都支持可重入 可重入 可重入是指用一个线程如果首次获得了这把锁,那么因为它是这把锁的拥有者,因此有权利再次获取这把锁 如果是不可重入锁,那么第二次获得锁时,自己也会被锁挡住 基本语法 同步模式之顺序控制 固定运行顺序 比如,必须先2后1打印 wait notify版 交替输出 线程1输出a5次,线程2输出b5次,线程3输出c5次

锁分类介绍

旧街凉风 提交于 2020-02-10 20:44:31
本博客系列是学习并发编程过程中的记录总结。由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅。 并发编程系列博客传送门 乐观锁和悲观锁 锁从宏观上来分类,可以分为悲观锁与乐观锁。注意,这里说的的锁可以是数据库中的锁,也可以是Java等开发语言中的锁技术。悲观锁和乐观锁其实只是一类概念(对某类具体锁的总称),不是某种语言或是某个技术独有的锁技术。 乐观锁 是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,采取在写时先读出当前版本号,然后加锁操作(比较跟上一次的版本号,如果一样则更新),如果失败则要重复读-比较-写的操作。java中的乐观锁基本都是通过CAS操作实现的,CAS是一种更新的原子操作,比较当前值跟传入值是否一样,一样则更新,否则失败。数据库中的共享锁也是一种乐观锁。 悲观锁 是就是悲观思想,即认为写多,遇到并发写的可能性高,每次去拿数据的时候都认为别人会修改,所以每次在读写数据的时候都会上锁,这样别人想读写这个数据就会block直到拿到锁。java中典型的悲观锁就是Synchronized,AQS框架下的锁则是先尝试cas乐观锁去获取锁,获取不到,才会转换为悲观锁,如ReentrantLock。数据库中的排他锁也是一种悲观锁。

java线程同步--lock锁(JDK 5 新增)

大憨熊 提交于 2020-02-08 16:34:35
需手动加锁和释放. package com.LearnJava.Thread; import java.util.concurrent.locks.ReentrantLock; /* 同步代码块 synchronized(同步监视器){ //需要同步的代码 } 同步监视器:俗称 锁,可以是任何实例化的类.但是需要共用同一个实例. */ class WindowSell implements Runnable{ ReentrantLock lock = new ReentrantLock(); private int ticket = 100; @Override public void run() { while (true) { try { lock.lock(); if (ticket > 0) { System.out.println(Thread.currentThread().getName() + "sell " + ticket--); Thread.sleep(100); }else{ break; } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } } } public class ThreadTestTicket { public

简单看看ReentrantLock

感情迁移 提交于 2020-02-05 16:01:04
  前面我们分析了AQS的基本原理,然后也试着基于AQS实现了一个可重入的锁了,现在我们再来看看官方的ReentrantLock锁,这个锁是可重入的独占锁,也就是说同时只有一个线程可以获取该锁,而且这个线程还能继续尝试获取锁; 一.简单的使用   我们先根据ReentrantLock来简单实现一个线程安全的List,然后再分析常用的方法; package com.example.demo.study; import java.util.ArrayList; import java.util.concurrent.locks.ReentrantLock; public class Study0204 { //线程不安全的List private ArrayList<String> list = new ArrayList<String>(); //独占锁,默认是非公平锁,传入true可以是公平锁 private volatile ReentrantLock lock = new ReentrantLock(); //往集合中添加元素 public void add(String str) { lock.lock(); try { list.add(str); } finally { lock.unlock(); } } //删除集合中的元素 public void remove

吃透Java并发十三:juc-locks之ReentrantLock

佐手、 提交于 2020-02-02 20:35:07
一、ReentrantLock类简介 ReentrantLock类,实现了Lock接口,是一种可重入的独占锁,它具有与使用 synchronized 相同的一些基本行为和语义,但功能更强大。ReentrantLock内部通过内部类实现了AQS框架(AbstractQueuedSynchronizer)的API来实现独占锁的功能。 ReentrantLock类的其中一个构造器提供了指定公平策略 / 非公平策略的功能,默认为非公平策略。 公平策略:在多个线程争用锁的情况下,公平策略倾向于将访问权授予等待时间最长的线程。也就是说,相当于有一个线程等待队列,先进入等待队列的线程后续会先获得锁,这样按照“先来后到”的原则,对于每一个等待线程都是公平的。 非公平策略:在多个线程争用锁的情况下,能够最终获得锁的线程是随机的(由底层OS调度)。 一般情况下,使用公平策略的程序在多线程访问时,总体吞吐量(即速度很慢,常常极其慢)比较低,因为此时在线程调度上面的开销比较大。 举个例子: 假设采用公平策略,线程A首先获取了锁,线程B和线程C等待获取锁,如下图: 当线程A释放锁时,线程B将经历从 挂起->唤醒 的线程调度过程,线程调度非常耗时。 在线程B的 挂起->唤醒 阶段: 如果采用非公平策略,那么线程C可以立即获取锁,线程C使用完并释放锁后,线程B可能才刚唤醒完成;此时线程B又可以去获取锁

【架构师技巧分享】程序员面试美团:面试官突然问Java “锁”你应该怎么回答?

天涯浪子 提交于 2020-02-02 18:02:15
【架构师技巧分享】程序员面试美团:面试官突然问Java “锁”你应该怎么回答? Java提供了种类丰富的锁,每种锁因其特性的不同,在适当的场景下能够展现出非常高的效率。本文旨在对锁相关源码(本文中的源码来自JDK 8)、使用场景进行举例,为读者介绍主流锁的知识点,以及不同的锁的适用场景。 Java中往往是按照是否含有某一特性来定义锁,我们通过特性将锁进行分组归类,再使用对比的方式进行介绍,帮助大家更快捷的理解相关知识。下面给出本文内容的总体分类目录: 1.乐观锁 VS 悲观锁 乐观锁与悲观锁是一种广义上的概念,体现了看待线程同步的不同角度。在Java和数据库中都有此概念对应的实际应用。 先说概念。对于同一个数据的并发操作,悲观锁认为自己在使用数据的时候一定有别的线程来修改数据,因此在获取数据的时候会先加锁,确保数据不会被别的线程修改。Java中,synchronized关键字和Lock的实现类都是悲观锁。 而乐观锁认为自己在使用数据时不会有别的线程修改数据,所以不会添加锁,只是在更新数据的时候去判断之前有没有别的线程更新了这个数据。如果这个数据没有被更新,当前线程将自己修改的数据成功写入。如果数据已经被其他线程更新,则根据不同的实现方式执行不同的操作(例如报错或者自动重试)。 乐观锁在Java中是通过使用无锁编程来实现,最常采用的是CAS算法