java多线程的锁整理
参考,欢迎点击原文:https://www.jianshu.com/p/473a3d96a1b0(java锁总结)
https://www.jianshu.com/p/dcabdf695557(ReentrantLock深入理解)
https://www.cnblogs.com/xd502djj/p/9873067.html(volatile)
自然而然在多线程的情况下就得使用锁来保证资源的准确性,今天整理下java锁的知识
锁: 并发环境下多个线程会对同一资源进行争抢,可能会导致数据不一致问题,引入锁机制,对资源进行锁定
锁使用类型:
可重入锁: 执行同步方法,不用可再次获得锁ReentrantLock
可中断锁: 在等待获取锁过程中可中断
公平锁: 等待时间越长,越优先获取锁权利
读写锁: 读可以多线程读,写必须同步的写
乐观悲观锁类型
乐观锁: cas编程思想,ReentrantLock使用(jdk)显示锁
悲观锁: synchronized使用(jvm)隐式锁
Synchroned和lock区别
- Synchroned是关键字,lock是java类
- Synchroned无法获取锁状态、自动,lock纯手动
- Synchroned可重入,不可中断,非公平;lock也可重入,单可中断,可公可不公
详解以上两种锁:
- 三剑客:Synchroned + wait + notify
- 新三剑客:lock + await + signal(后面两个属于condition里面的 )
Synchronization(非公平锁):
简介: 业务简单的情况下使用,是jdk自带的原来比较重,依赖jvm,现在优化了,自适应自旋,有变化了再自旋。编译后生成监视器锁monitorenter,实现锁定。
tip:
Synchroned中使用的wait应该是放在while中,否则只是被通知判断一次,造成虚假唤醒
synchronized的四种形态(New无锁-》偏向锁-》轻量级锁-》重量级锁):
无锁: 不锁资源
偏向锁: 当某块资源被线程抢到时就回拿到锁,后续该线程访问这块资源无需获取锁了,提高性能(没有竞争)
轻量级: 什么时候触发升级?1、关闭了偏向锁,2、多个线程竞争了,偏向锁会自动升级成轻量级锁,有了多个自旋(少量,且时间短)
重量级: 自旋到一定次数时,且多个在等待,那就进队列,等操作系统调用,性能低下(很多,且时间长)
使用: 非静态方法: 锁定的是方法,class模板就一个这个
静态方法: 锁定的是类,new出来的对象
例子:
- synchronized块就看锁的对象有几个,数字超过127就需要按悲观锁排队执行,不超过就不用悲观锁,因为都是常量是固定的对象需要排队,如参数int num=4,虽然new出来的是多个地址,但是区间在-128~127没超过是常量,超过是new
- 比如开十个线程,累加1000,最后会小于10000,Volatile保证:可见性,有序性,synchornized保证:原子性
ReentrantLock(公平锁和非公平):
业务复杂,需要手动加锁lock和解锁unlock,解锁的操作尽量要放在finally代码块中,灵活度较高。
可通过 ReadWriteLock 读写锁,写的时候其他都不能动。
利用CAS+AQS队列来实现,通过设置参数fair实现公平非公平锁。他的公平锁使用的就是aqs思想
死锁
产生原因: 线程1得到了锁A,在锁A未释放时,希望获得锁B
线程2获得了锁B,在锁B未释放时,希望获得锁A
解决办法:
不要在锁里再请求锁
使用信号量尝试获取锁trylock,设置尝试次数和超时时间
1、
Jps -l // 查看定位进程号2、jsack 进程号
CAS和AQS基类框架
CAS(Compare And Swap乐观锁):
- 英文翻译是比较和交换,Aomic(AtomicInteger)就是使用这个机制实现的,这个比synchronized悲观锁效率高,自旋循环会耗时
- 如果内存位置V的值与预期原值A相匹配,那么处理器会自动将该位置V的值更新为新值B
- ABA问题,A->B->A,但是cas没有发现变化,是个问题,可以使用版本号来避免,如AtomicStampedRefrence(1,1)//只能在127内
- Unsafe:实际使用的是native,c++获取内存的值进行比较和操作的
AQS(AbstractQueuedSynchronizer):
- 原理:维护volatile,同时检查是否能拿到锁,如果不能拿到就fifo模式排队。
Volatile(汇编语言): 保证多线程之间副本变量的可见性,需要搭配synchronized使用
底层实现(早期-性能低):
- 先从“主内存”将数据读取read写到load工作内存
- use使用该值,使用assign赋值到工作内存中
- 将工作内存的变量存储store并写入write到主内存
Volatile(保证和让使用该资源见到):是java虚拟机提供轻量级的同步机制
1、保证可见性
2、不保证原子性!==》使用原子类volatile atomic这样用
3、禁止指令重排
Mesi缓存一致性协议:总线上的监听机制,汇编语言lock指令
通过控制volatitle int state加锁,可加独占锁(Exclusive)也可加共享锁
JUC:
简介: java.util .concurrent工具包的简称。这是一个处理线程的工具包
提供了这些包: tools,executor,atomic(原子性包),locks(锁包),collections(集合类)
Tomic类自旋锁实现了cas
Tip:
- 使用读写锁 readWriteLock.writeLock.lock() readWriteLock.writeLock.unlock()
- Cpu密集型使用cpu核数线程,io使用cpu数量的两倍
- 指定线程唤醒,new三个condition,然后不同的调用(视频)
大数据量处理:
ForkJoin:工作窃取,维护的双端队列
forkJoinPool,stream并行流
ArrayBlockingQueue(可 设置大小)
1、add remove element(检查队首元素)会抛异常
2、offer poll peek(检查队首元素) take(等待着拿)不会抛
线程异步执行:
completablefuture.runAsync// 没有返回值
completablefuture.supplyAsync// 有返回值
代码样例
// synchronized
Integer number = 3;
public synchronized void increment() throws InterruptedException {
if(number != 0){
this.wait();
}
number++;
this.notifyAll();
}
// synchronized+lock
private Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
public synchronized void increment() throws InterruptedException {
lock.lock();
try {
while (number != 0){
condition.await();
}
// todo
condition.asign();
}catch (){
}finally {
lock.unlock();
}
}
// countDownLatch
CountDownLatch countDownLatch = new CountDownLatch(6);
countDownLatch.countDown();
countDownLatch.await();// 等待减到零
java多线程的锁整理的更多相关文章
- JAVA多线程与锁机制
JAVA多线程与锁机制 1 关于Synchronized和lock synchronized是Java的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码 ...
- Java 多线程:锁(一)
Java 多线程:锁(一) 作者:Grey 原文地址: 博客园:Java 多线程:锁(一) CSDN:Java 多线程:锁(一) CAS 比较与交换的意思 举个例子,内存有个值是 3,如果用 Java ...
- Java 多线程:锁(二)
Java 多线程:锁(二) 作者:Grey 原文地址: 博客园:Java 多线程:锁(二) CSDN:Java 多线程:锁(二) AtomicLong VS LongAddr VS Synchroni ...
- Java 多线程:锁(三)
Java 多线程:锁(三) 作者:Grey 原文地址: 博客园:Java 多线程:锁(三) CSDN:Java 多线程:锁(三) StampedLock StampedLock其实是对读写锁的一种改进 ...
- Java多线程面试题整理
部分一:多线程部分: 1) 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速. ...
- 53道java多线程面试题整理及答案(2018年)
最近看到网上流传着,各种面试经验及面试题,往往都是一大堆技术题目贴上去,而没有答案. 为此我业余时间整理了Java多线程相关的53道常见面试题,及详细答案,你可以用它来好好准备面试.望各路大牛,发现不 ...
- java多线程面试题整理及答案(2018年)
1) 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理器编程,你可以使用多线程对 运算密集型任务提速.比如,如果一个线程完 ...
- java多线程面试题整理及回答
1)现在有T1.T2.T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行? 这个线程问题通常会在第一轮或电话面试阶段被问到,目的是检测你对”join”方法是否熟悉.这个多线程问题比 ...
- java多线程----悲观锁与乐观锁
java多线程中悲观锁与乐观锁思想 一.悲观锁 总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线 ...
- java多线程面试题整理及答案(2019年)
1) 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理器编程,你可以使用多线程对 运算密集型任务提速.比如,如果一个线程完 ...
随机推荐
- DDR5能给PC带来怎样提升?我们用12款软件进行了对比测试
结论前置:我们使用了12款专业测试软件,分别对DDR5与DDR4内存,在相同平台下进行了测试体验:酷睿i9-12900K搭配DDR4与DDR5,总体差距并不是很大:在y-cruncher测试中,DDR ...
- Docker从认识到实践再到底层原理(九)|Docker Compose 容器编排
前言 那么这里博主先安利一些干货满满的专栏了! 首先是博主的高质量博客的汇总,这个专栏里面的博客,都是博主最最用心写的一部分,干货满满,希望对大家有帮助. 高质量博客汇总 然后就是博主最近最花时间的一 ...
- 基数排序|RadixSort|C++实现
前言 那么这里博主先安利一些干货满满的专栏了! 首先是博主的高质量博客的汇总,这个专栏里面的博客,都是博主最最用心写的一部分,干货满满,希望对大家有帮助. 高质量干货博客汇总https://blog. ...
- npm script 详解,tsc && electron . 直接编译后 运行,非常方便
最终平时只需要用这个方法就可以了: tsc && electron . ======================================================== ...
- 【译】使用.NET将WebAssembly扩展到云(二)
原文 | Richard Lander 翻译 | 郑子铭 轻量级功能 嗯--但是如果我们使用 Wasm 更像是一个典型的功能而不是一个应用程序,我们可能不会计算一百万个单词,而是做一些更轻量级的事情. ...
- CentOS7中搭建GitLab踩坑实录
今晚闲来无事,尝试了下自己搭建一台git服务器,很多人可能不明白平时自己随手就可以提交代码,为什么还要自己搭建服务器呢?首先你有没有考虑过你是怎么能把代码提交上去的?如果公司突然有一天需要你来负责搭建 ...
- 【Unity3D】碰撞体组件Collider
1 前言 Unity3D 中碰撞体(Collider)组件用于检测运动的物体之间是否发生碰撞,也可以作为触发器使用.产生碰撞的条件是: 2 个游戏对象都有 Collider 至少有一个游戏对象有 ...
- Java中的POJO是什么?
1.介绍 在这个简短的教程中,我们将研究"普通Java对象"(Plain Old Java Object)的定义,简称POJO.我们将看看POJO与JavaBean的比较,以及如何 ...
- Direct2D 几何篇
微软文档:Geometries overview 本篇通过官方文档学习,整理出来的demo,初始样本请先创建一个普通的desktop app. // Test_Direct2D_Brush.cpp : ...
- 麒麟系统开发笔记(八):在国产麒麟系统上使用linuxdeployqt发布qt程序
前言 在ubuntu上发布qt程序相对还好,使用脚本,但是在麒麟上发布的时候,因为银河麒麟等不同版本,使用脚本就不太兼容,同时为了实现直接点击应用可以启动应用的效果,使用linuxdeployqt ...