java多线程的锁整理

编程入门 行业动态 更新时间:2024-10-08 07:38:33

java<a href=https://www.elefans.com/category/jswz/34/1767532.html style=多线程的锁整理"/>

java多线程的锁整理

参考,欢迎点击原文:(java锁总结)
(ReentrantLock深入理解)
.html(volatile)

自然而然在多线程的情况下就得使用锁来保证资源的准确性,今天整理下java锁的知识

锁🔒: 并发环境下多个线程会对同一资源进行争抢,可能会导致数据不一致问题,引入锁机制,对资源进行锁定

锁使用类型:
可重入锁: 执行同步方法,不用可再次获得锁ReentrantLock
可中断锁: 在等待获取锁过程中可中断
公平锁: 等待时间越长,越优先获取锁权利
读写锁: 读可以多线程读,写必须同步的写

乐观悲观锁类型
乐观锁: cas编程思想,ReentrantLock使用(jdk)显示锁
悲观锁: synchronized使用(jvm)隐式锁

Synchroned和lock区别

  1. Synchroned是关键字,lock是java类
  2. Synchroned无法获取锁状态、自动,lock纯手动
  3. 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使用
底层实现(早期-性能低):

  1. 先从“主内存”将数据读取read写到load工作内存
  2. use使用该值,使用assign赋值到工作内存中
  3. 将工作内存的变量存储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// 有返回值

代码样例

// synchronizedInteger number = 3;public synchronized void increment() throws InterruptedException {if(number != 0){this.wait();}number++;this.notifyAll();}// synchronized+lockprivate Lock lock = new ReentrantLock();Condition condition = lock.newCondition();public synchronized void increment() throws InterruptedException {lock.lock();try {while (number != 0){condition.await();}// todocondition.asign();}catch (){}finally {lock.unlock();}}// countDownLatchCountDownLatch countDownLatch = new CountDownLatch(6);countDownLatch.countDown();countDownLatch.await();// 等待减到零

更多推荐

java多线程的锁整理

本文发布于:2024-02-07 09:04:58,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1755926.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:多线程   java

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!