Java并发包之闭锁/栅栏/信号量及并发模型和锁
threadLocal能够为每一个线程维护变量副本,常用于在多线程中用空间换时间
进程死锁:进程死锁,指多个进程循环等待他方占有的资源而一直等待下去的局面;
进程活锁:线程1,2需要同时占有a,b才可以,1占有a,2占有b,为了避免死锁,1,2分别释放,a,b空闲,此时1,2又同时抢锁,发生活锁;(电梯上遇到人,一个进一个出,2个人同时往一个方向让路,来回反复)
进程饥饿:指某一个或多个线程因为各种原因无法获取所需要的资源,导致一直无法执行;
一、乐观锁
总是认为不会产生并发问题,每次去取数据的时候总认为不会有其他线程对数据进行修改,因此不会上锁,但是在更新时会判断其他线程在这之前有没有对数据进行修改,一般会使用版本号机制或CAS操作实现。 乐观锁适用于多读的应用类型,这样可以提高吞吐量
version方式:一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功。
核心SQL代码:
update table set x=x+1, version=version+1 where id=#{id} and version=#{version};
CAS操作方式:即compare and swap 或者 compare and set,涉及到三个操作数,数据所在的内存值,预期值,新值。当需要更新时,判断当前内存值与之前取到的值是否相等,若相等,则用新值更新,若失败则重试,一般情况下是一个自旋操作,即不断的重试。
一、悲观锁
总是假设最坏的情况,每次取数据时都认为其他线程会修改,所以都会加锁(读锁、写锁、行锁等),当其他线程想要访问数据时,都需要阻塞挂起。可以依靠数据库实现,如行锁、读锁和写锁等,都是在操作之前加锁,在Java中,synchronized的思想也是悲观锁。 (共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。
对于资源竞争较少(线程冲突较轻)的情况,使用synchronized同步锁进行线程阻塞和唤醒切换以及用户态内核态间的切换操作额外浪费消耗cpu资源;而CAS基于硬件实现,不需要进入内核,不需要切换线程,操作自旋几率较少,因此可以获得更高的性能。
对于资源竞争严重(线程冲突严重)的情况,CAS自旋的概率会比较大,从而浪费更多的CPU资源,效率低于synchronized。
。synchronized的底层实现主要依靠 Lock-Free 的队列,基本思路是 自旋后阻塞,竞争切换后继续竞争锁,稍微牺牲了公平性,但获得了高吞吐量。在线程冲突较少的情况下,可以获得和CAS类似的性能;而线程冲突严重的情况下,性能远高于CAS。
传统的并发模型:每个I/O流都有一个新的线程管理;
I/O多路复用:只有单个线程,通过跟踪每个I/O流的状态,来管理多个I/O流;
(我们都redis-client在操作的时候,会产生具有不同事件类型的socket。在服务端,有一段I/O多路复用程序,将其置入队列之中,然后,文件事件分派器,依次去队列中取,转发到不同的事件处理器中)
Java并发包之闭锁/栅栏/信号量
Java并发包之闭锁/栅栏/信号量
1.提供内存可见性和防止指令重排的volatile属于jvm关键字
2.而java.util.concurrent包(J.U.C)中包含的是java并发编程中有用的一些工具类,包括几个部分:
- locks部分:包含在java.util.concurrent.locks包中,提供显式锁(互斥锁和速写锁)相关功能。
- atomic部分:包含在java.util.concurrent.atomic包中,提供原子变量类相关的功能,是构建非阻塞算法的基础。
- executor部分:散落在java.util.concurrent包中,提供线程池相关的功能。
- collections部分:散落在java.util.concurrent包中,提供并发容器相关功能。
- tools部分:散落在java.util.concurrent包中,提供同步工具类,如信号量、闭锁、栅栏等功能。
1、Semaphore信号量:跟锁机制存在一定的相似性,semaphore也是一种锁机制,所不同的是,reentrantLock是只允许一个线程获得锁,而信号量持有多个许可(permits),允许多个线程获得许可并执行。可以用来控制同时访问某个特定资源的操作数量,或者同时执行某个指定操作的数量。
2、CountDownLatch闭锁:允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行。CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。
主要方法:
1. CountDownLatch.await():将某个线程阻塞住,直到计数器count=0才恢复执行。
2. CountDownLatch.countDown():将计数器count减1。
3、CyclicBarrier栅栏:用于阻塞一组线程直到某个事件发生。所有线程必须同时到达栅栏位置才能继续执行下一步操作,且能够被重置以达到重复利用。而闭锁是一次性对象,一旦进入终止状态,就不能被重置。
闭锁用于一组线程等待(阻塞)一个外部事件的发生,这个事件发生之前这些线程阻塞,等待控制线程打开闭锁,然后这些线程同时开始执行。闭锁强调的是阻塞后的同时开始;
栅栏则是一组线程相互等待,直到所有线程都到达某一点时才打开栅栏,然后线程可以继续执行,也就是说控制线程先设置一个时间点,然后这些线程各自执行,执行完等待(阻塞),直到这组线程中的所有线程执行完,然后控制线程栅栏打开,这些线程同时继续执行。栅栏强调的是各自执行完后的相互等待以及继续执行。
信号量根据一个计数器控制一个结果的数量,条件满足情况下才能进行增加和移除操作,否则进行操作的线程阻塞。
场景对比:
l 闭锁场景:几个人相约去公园游玩,在家做好准备,约定在某一时刻同时出发去公园,准备工作进行的快的不能提前出门,到点出门。
l 栅栏场景:几个人相约去公园游玩,几个人去到公园门口,要等全部到达公园门口后才一起进入公园。
l 信号量场景:几个人相约去公园游玩,等大家都到公园后,发现来的太迟了,公园游客饱和,公园限制入场游客的数量。游客在门口等待,出来一人,再进入一人,只能一个一个进入。
缓存
页面缓存经常用在CMS(content manage system)内存管理系统里面。
数据缓存经常会用在页面的具体数据里面。
页面缓存(smarty静态化技术)
第一次从数据库读取,然后生成一个静态页面,以后所有的读取,只加载这个静态页面就可以了‘’
数据缓存
由于一个页面有好几种需要从不同的缓存中读取数据的模块,所以不适合使用页面缓存
Java并发包之闭锁/栅栏/信号量及并发模型和锁相关推荐
- Java并发包之闭锁/栅栏/信号量(转)
本文转自http://blog.csdn.net/u010942020/article/details/79352560 感谢作者 一.Java多线程总结: 描述线程的类:Runable和Thread ...
- java 信号量 闭锁_Java并发包之闭锁/栅栏/信号量
二.同步工具类详解 1.Semaphore信号量:跟锁机制存在一定的相似性,semaphore也是一种锁机制,所不同的是,reentrantLock是只允许一个线程获得锁,而信号量持有多个许可(per ...
- java多线程并发之旅-20-同步工具类。闭锁/栅栏/信号量/阻塞队列/FutureTask
同步工具类 同步工具类主要包括闭锁(如CountDownLatch),栅栏(如CyclicBarrier),信号量(如Semaphore)和阻塞队列(如LinkedBlockingQueue)等: F ...
- java并发编程笔记3-同步容器并发容器闭锁栅栏信号量
一.同步容器: 1.Vector容器实现了List接口,Vector实际上就是一个数组,和ArrayList类似,但是Vector中的方法都是synchronized方法,即进行了同步措施.保证了线程 ...
- Java多线程并发编程--Java并发包(JUC)
Java多线程并发–Java并发包(JUC) 前言 前一篇文章中,笔者已经介绍了Java多线程的一些基础知识,但是想要成为一名中高级Java程序员还必须懂得Java并发包(JUC)的知识点,而且JUC ...
- Java并发包下的辅助工具类
Java并发包下为我们提供了一些辅助工具类,来简单看看如何使用 一.CountDownLatch 减法器,必须等到减法器的值为0了,才能继续往下执行.也可以将它理解为栅栏 让一些线程堵塞直到另一个线程 ...
- 第 5-6 课:Java 并发包中的高级同步工具 + 面试题
Java 中的并发包指的是 java.util.concurrent(简称 JUC)包和其子包下的类和接口,它为 Java 的并发提供了各种功能支持,比如: 提供了线程池的创建类 ThreadPool ...
- java并发包线程池原理分析锁的深度化
java并发包&线程池原理分析&锁的深度化 并发包 同步容器类 Vector与ArrayList区别 1.ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素 ...
- Java并发编程初级-未使用Java并发包的时候
转自Java并发编程网 http://ifeve.com/java_multi_thread_programming_1_2/ 本文介绍了Java原生的多线程技术(1.2),通过详细介绍wait和 ...
最新文章
- windows8不能更新?
- golang web 框架 gin beego iris 对比
- mysql iops_MySQL实例IOPS使用率高的原因和解决方法
- 2013年11月份我国网络不良与垃圾短信息分析报告
- Kylin报错classnotfound:org.apache.hadoop.hive.serde2.typeinfo.typeInfo
- node.js用get方式获取网页中的链接
- mysql中的视图_分布式 | DBLE 是如何实现视图的?
- 计算机考级各省份难度,2018年全国各省份高考难度排名,基于高分率最新统计数据!...
- linux history 用法,Linux之History的使用
- 数据库授予用户增删改查的权限的语句_mysql数据库终端上的增删改查及权限等相关操作...
- Android Studio 快速实现上传项目到Github(详细步骤)
- Matlab时间序列分析
- 解析损失函数、代价函数、目标函数
- chromium浏览器_什么是Chrome? Chromium网络浏览器与Chrome有何不同
- 计算机重启后e盘没了,Win10电脑怎么隐藏磁盘分区?
- Linus Torvalds的最新电脑配置
- java 正斜杠与反斜杠之分
- 一文全懂,Android程序员最新职业规划
- pthread_cancel引起程序段错误
- 记一次富途集团后台开发笔试
热门文章
- mysql any all some
- Python 绘制饼图时同时在每一块上显示数值和占比
- CreateMutex WaitForSingleObject ReleaseMutex使用
- 前后端分离之评论功能前端(1)——django+mysql+vue+element+axios
- AngularJS入门教程06:链接与图片模板
- 强化学习(一)Fundamentals of Reinforcement Learning
- 聚焦社群本质,规避社群营销的九大雷区
- xpath自定义属性值的取法
- 关于Google浏览器书签识别不了问题
- oracle空实例连接报错01017,分享些工作中遇到的奇怪问题以及解决方案