reentrantlock

redis分布式锁

两盒软妹~` 提交于 2019-12-05 07:18:49
关于分布式锁的概念网上太多了,这里就不罗嗦了。对于开发者来说,最关心的应该是什么情况下使用分布式锁。 使用分布式锁,一般要满足以下几个条件: · 分布式系统(关键是分布式) · 共享资源(各系统访问同一资源,资源的载体可能是传统关系型数据库或者NoSQL) · 同步访问(没有同步访问,谁管你资源竞争不竞争) 场景案例 · 光说不练假把式,上点干货。管理后台的部署架构(多台tomcat服务器+redis+mysql)就满足使用分布式锁的条件。多台服务器要访问redis全局缓存的资源,如果不使用分布式锁就会出现问题。 看如下伪代码: long N=0L; //N从redis获取值 if(N<5){ N++; //N写回redis } · 从redis获取值N,对数值N进行边界检查,自加1,然后N写回redis中。 这种应用场景很常见,像秒杀,全局递增ID、IP访问限制等。以IP访问限制来说,恶意攻击者可能发起无限次访问,并发量比较大,分布式环境下对N的边界检查就不可靠,因为从redis读的N可能已经是脏数据。传统的加锁的做法(如java的synchronized和Lock)也没用,因为这是分布式环境,这个同步问题的救火队员也束手无策。在这危急存亡之秋,分布式锁终于有用武之地了。 所谓知己知彼,百战百胜。要想用好他,首先你要了解他。分布式锁可以基于很多种方式实现,比如zookeeper

初识Lock与AbstractQueuedSynchronizer(AQS)

别等时光非礼了梦想. 提交于 2019-12-04 20:36:10
本人免费整理了Java高级资料,涵盖了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo高并发分布式等教程,一共30G,需要自己领取。 传送门: https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q 1. concurrent包的结构层次 在针对并发编程中,Doug Lea大师为我们提供了大量实用,高性能的工具类,针对这些代码进行研究会让我们队并发编程的掌握更加透彻也会大大提升我们队并发编程技术的热爱。这些代码在java.util.concurrent包下。如下图,即为concurrent包的目录结构图。 其中包含了两个子包:atomic以及lock,另外在concurrent下的阻塞队列以及executors,这些就是concurrent包中的精华,之后会一一进行学习。而这些类的实现主要是依赖于volatile以及CAS(关于volatile可以看 这篇文章 ,关于CAS可以看 这篇文章的3.1节 ),从整体上来看concurrent包的整体实现图如下图所示: 2. lock简介 我们下来看concurent包下的lock子包。锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源。在Lock接口出现之前

Java多线程总结之聊一聊Queue

廉价感情. 提交于 2019-12-04 19:46:37
上个星期总结了一下synchronized相关的知识,这次将Queue相关的知识总结一下,和朋友们分享。 在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列。Java提供的线程安全的Queue可以分为 阻塞队列和非阻塞队列 ,其中阻塞队列的典型例子是BlockingQueue,非阻塞队列的典型例子是ConcurrentLinkedQueue,在实际应用中要根据实际需要选用阻塞队列或者非阻塞队列。 注:什么叫 线程安全 ?这个首先要明确。线程安全的类 ,指的是类内共享的全局变量的访问必须保证是不受多线程形式影响的。如果由于多线程的访问(比如修改、遍历、查看)而使这些变量结构被破坏或者针对这些变量操作的原子性被破坏,则这个类就不是线程安全的。 今天就聊聊这两种Queue,本文分为以下两个部分,用分割线分开: BlockingQueue ConcurrentLinkedQueue,非阻塞算法 首先来看看 BlockingQueue : Queue是什么就不需要多说了吧,一句话:队列是先进先出。相对的,栈是后进先出。如果不熟悉的话先找本基础的数据结构的书看看吧。 BlockingQueue,顾名思义,“阻塞队列”:可以提供阻塞功能的队列。 首先,看看BlockingQueue提供的常用方法: 可能报异常 返回布尔值 可能阻塞 设定等待时间 入队 add(e)

java多线程面试题总结(转载)

丶灬走出姿态 提交于 2019-12-04 19:43:27
文章转载自 40个Java多线程问题总结 ####40个问题汇总结 #####多线程有什么用 发挥多核CPU的优势 随着工业的进步,现在的笔记本、台式机乃至商用的应用服务器至少也都是双核的,4核、8核甚至16核的也都不少见,如果是单线程的程序,那么在双核CPU上就浪费了50%,在4核CPU上就浪费了75%。单核CPU上所谓的"多线程"那是假的多线程,同一时间处理器只会处理一段逻辑,只不过线程之间切换得比较快,看着像多个线程"同时"运行罢了。多核CPU上的多线程才是真正的多线程,它能让你的多段逻辑同时工作,多线程,可以真正发挥出多核CPU的优势来,达到充分利用CPU的目的。 防止阻塞 从程序运行效率的角度来看,单核CPU不但不会发挥出多线程的优势,反而会因为在单核CPU上运行多线程导致线程上下文的切换,而降低程序整体的效率。但是单核CPU我们还是要应用多线程,就是为了防止阻塞。试想,如果单核CPU使用单线程,那么只要这个线程阻塞了,比方说远程读取某个数据吧,对端迟迟未返回又没有设置超时时间,那么你的整个程序在数据返回回来之前就停止运行了。多线程可以防止这个问题,多条线程同时运行,哪怕一条线程的代码执行读取数据阻塞,也不会影响其它任务的执行。 便于建模 这是另外一个没有这么明显的优点了。假设有一个大的任务A,单线程编程,那么就要考虑很多,建立整个程序模型比较麻烦

Java多线程之线程安全队列Queue

巧了我就是萌 提交于 2019-12-04 15:58:35
在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列。Java提供的线程安全的Queue可以分为 阻塞队列和非阻塞队列 ,其中阻塞队列的典型例子是BlockingQueue,非阻塞队列的典型例子是ConcurrentLinkedQueue,在实际应用中要根据实际需要选用阻塞队列或者非阻塞队列。 注:什么叫 线程安全 ?这个首先要明确。 线程安全的类 ,指的是 类内共享的全局变量的访问必须保证是 不受多线程形式影响的 。如果由于多线程的访问(比如修改、遍历、查看)而使这些变量结构被破坏或者针对这些变量操作的原子性被破坏,则这个类就不是线程安全的。 今天就聊聊这两种Queue,本文分为以下两个部分,用分割线分开: BlockingQueue 阻塞算法 ConcurrentLinkedQueue,非阻塞算法 首先来看看 BlockingQueue : Queue是什么就不需要多说了吧,一句话: 队列是先进先出 。相对的, 栈是后进先出 。如果不熟悉的话先找本基础的数据结构的书看看吧。 BlockingQueue,顾名思义,“阻塞队列”:可以提供阻塞功能的队列。 首先,看看BlockingQueue提供的常用方法: 可能报异常 返回布尔值 可能阻塞 设定等待时间 入队 add(e) offer(e) put(e) offer(e, timeout, unit)

java.concurrent.ReentrantLock - why we want to acquire the same lock multiple times [duplicate]

时光毁灭记忆、已成空白 提交于 2019-12-04 08:13:17
This question already has answers here : Why use a ReentrantLock if one can use synchronized(this)? (7 answers) Closed 6 years ago . I know if using ReentrantLock, it allows the same thread to acquire the same lock more than once. Internally, it has a counter to count the number of the lock acquisition. If you acquired the same lock twice, you would need to release it twice. But my question is that why would someone want to acquire the lock multiple times, should one time acquisition be enough? Can someone give me a common use case? Consider the following case in which you need a set of

多线程并发编程总结(二)

吃可爱长大的小学妹 提交于 2019-12-04 03:53:29
本文基于 https://github.com/h2pl/Java-Tutorial 的总结 ReentrantReadWriteLock(读写锁)源码分析 ReentrantReadWriteLock 分为读锁和写锁两个实例: 读锁是共享锁,可被多个线程同时使用,写锁是独占锁。 持有写锁的线程可以继续获取读锁(锁降级),反之不行(持有读锁必须先释放才能再次获取写锁)。 AQS 的精髓在于内部的属性 state: 独占模式,通常就是 0 代表可获取锁,>=1 代表锁被别人获取了。 共享模式下,每个线程都可以对 state 进行加减操作。 独占模式和共享模式对于 state 的操作完全不一样, 读写锁 ReentrantReadWriteLock 中是将 state 这个 32 位的 int 值分为高 16 位和低 16位, 分别用于共享模式和独占模式。 /** * 读锁 */ public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable { private final ReentrantReadWriteLock.ReadLock readerLock; private final ReentrantReadWriteLock.WriteLock writerLock;

死锁及其预防策略

允我心安 提交于 2019-12-04 02:24:06
什么是死锁? 如果一个进程集合中的每个进程都在等待只能只能有该集合中的其他一个进程才能引发的事件, 这种情况就是死锁。 简单举例 资源 A 与 资源 B 都是不可剥夺资源 进程 C 已经申请到资源A, 进程D已经申请到了资源B 进程 C 此时申请资源B, 而进程D恰好申请了资源A 由于资源已被占用, 进程A和进程B都无法执行下一步操作, 就造成了死锁。 产生死锁的四个必要条件 互斥条件 (Mutual exclusive) 资源不能被共享, 只能由一个进程使用。 请求与保持条件 (Hold and Wait) 已经得到资源的进程可以再次申请新的资源。 非剥夺条件 (No pre-emption) 已经分配的资源不能从相应的进程强制地剥夺。 循环等待条件 (Circular wait) 系统中若干进程组成环路, 该环路中每个进程都在等待相邻进程整占用的资源。 死锁处理策略 预防死锁 设置某些限制条件, 破坏产生死锁的四个必要条件中的一个或几个, 以预防发生死锁。 避免死锁 在资源动态分配中, 用某种方法防止系统进入不安全状态, 从而避免死锁。 死锁 检测 和 解除 无需采取任何限制性措施,允许进程在运行过程中发生死锁。通过系统检测机构及时地检测死锁的发生,然后采取某种措施解除死锁。 资源分配策略 各种可能模式 主要优点 主要缺点 死锁预防 保守, 宁可资源限制 一次请求所有的资源,

多线程并发编程总结(一)

為{幸葍}努か 提交于 2019-12-04 01:39:51
多线程的优缺点 多线程的优点: 资源利用率更好, 程序响应更快。 多线程的代价: 设计复杂, 上下文切换开销大(先存储当前线程的本地的数据,程序指针等,然后载入另一个线程的本地数据,程序指针等,最后才开始执行), 增加资源消耗(每个线程需要消耗的资源)。 线程的状态 new(新建) runnnable(可运行) running(运行) blocked(阻塞) waiting(等待) time waiting (定时等待) terminated(终止) JMM(Java内存模型) JMM定义了线程和主内存之间的抽象关系。 主内存是共享内存区域,所有线程都可以访问,但线程对变量的操作(读取赋值等)必须在工作内存(栈空间)中进行。 线程间的通信(传值)必须通过主内存来完成。 对于一个实例对象中的成员方法而言: 如果方法中包含本地变量是基本数据类型,将直接存储在工作内存的帧栈结构中, 但倘若本地变量是引用类型,那么该变量的引用会存储在功能内存的帧栈中,而对象实例将存储在主内存(共享数据区域,堆)中。 volatile写-读的内存语义 当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存。 当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效。线程接下来将从主内存中读取共享变量。 锁释放和获取的内存语义 当线程释放锁时

Does making a Reentrant Lock static and make it a mutex?

南笙酒味 提交于 2019-12-03 16:59:12
问题 In Brian Goetz's book, Java Concurrency in Practice, his example of a Reentrant lock is programmed like this: Lock lock = new ReentrantLock(); However, I am curious to know if changing the above code to: private static final Lock lock = new ReentrantLock(); causes the lock to now act as a mutex, or if it is unnecessary and redundant. Thus, does the functionality of this code change if the lock is made private, static, and final? lock.lock(); try { //method stuff } finally { lock.unlock(); }