当前位置: 首页 > news >正文

Java EE初阶 --多线程2

一. 常见的锁策略

1.悲观锁和乐观锁

悲观锁:总是假设是最坏的情况,认为锁竞争十分激烈,每次访问共享数据的时候,都认为别人回家修改它,所以每次访问共享数据的时候,都会先获取锁,其他线程想获取就得阻塞等待,进入到等待队列,工作流程为先加锁再操作

乐观锁:总是假设是最好的情况,认为锁竞争不激烈,访问共享数据时认为别人不会修改数据,所以不对数据进行加锁,工作流程为先操作再进行检查冲突

2.重量级锁和轻量级锁

悲观锁和乐观锁是加锁时遇到的场景,而重量级锁和轻量级锁是解决这些场景的解决方案,重量级锁是应对悲观锁的场景,轻量级锁是应对乐观锁的场景。

3.挂起等待锁和自旋锁

自旋锁:是轻量级锁的典型实现,应用程序级别的,当加锁式发现竞争,不会进入到阻塞状态,而是进入到忙等(不断的申请锁,直到拿到锁为止,此过程中要不断的消耗CPU,但在乐观锁的场景下,可以短时间内拿到锁)的状态。

挂起等待锁:是重量级锁的典型实现,操作内核级别的,加锁时遇到竞争时,会进入到阻塞状态,进入到等待队列,不会持续消耗CPU,此时可以拿CPU做其他事,后续要操作内核进行唤醒了

4.普通互斥锁和读写锁

互斥锁:如Java中的 synchronized

读写锁:把读和写操作区分对待,Java标准库提供了ReentrantReadWriteLock类,实现了读写锁,其类下有ReentrantReadWriteLock.ReadLock类表示读锁和ReentrantReadWriteLock.WriteLock类表示写锁,并分别提供了lock和unlock方法进行加锁和解锁。其中读和读操作不会互斥,多个线程可以同时读,而读和写操作、写和写操作会互斥

5.可重入锁和不可重入锁(讲过)

6.公平锁和非公平锁

公平锁:遵从“先来后到”,多个线程申请一个刚释放的锁时,谁先申请谁就先拿到锁

非公平锁:不遵从“先来后到”,谁都有机会拿到锁

二.synchronized原理

1.synchronized遵从那些锁策略

synchronized始终是悲观锁具有自适应性JVM内部会统计锁竞争程度,根据锁竞争程度会从偏向锁→轻量级锁→重量级锁逐步升级)、可从入锁、非公平锁、普通互斥锁

2.加锁过程

JVM将synchronized关键字分为无锁、偏向锁、轻量级锁、重量级锁。会根据情况,进行依次升级

加锁过程解析:在未刚进入synchronized时为无锁状态,一旦进入到synchronized,不会真正加锁,而是对锁进行标记,此时由无锁转化成偏向锁,该操作比加锁轻量很多,如果其他线程没有来竞争该锁,最终该线程执行代码解锁过程只是把这个标记清除如果其他线程来竞争该锁,该线程会在锁被其他线程拿到之前加上锁,此时就是真正加锁了,从偏向锁转化为轻量级锁,如果JVM发现该锁竞争十分激烈,轻量级锁就会转化为重量级锁

三.锁消除

是编译器优化的体现,编译器会自行判断某代码块是否需要加锁,如果不需要,即使用户自己加上synchronized,但在编译后生成的机器码消除。

四.锁粗化

锁粒度指的是同步块保护的共享资源范围大小

锁粗化就是针对反复对细粒度的代码块加锁时,就有可能优化成一次加锁操作和解锁操作,此时锁的粒度就会变粗,这就是锁粗化。

五.CAS

1.什么是CAS

CAS:  全称为Compare And Swap,意思为比较和交换。CAS本质上是CPU指令,操作系统对该指令进行了封装,并提供了api给C++来使用,而JVM又是基于C++实现的,所以JVM可以通过C++调用CAS操作了,单都是由JVM和标准库封装好了。

2.CAS伪代码

注意:该代码块不是原子的,而真实的CAS操作是原子操作

3.CAS的使用

3.1 实现了原子类

Java标准库提供了java.util.concurrent.atomic包,里面对各种类型(如int、long等类型)进行了封装,都是基于CAS操作实现的,如之前的count++涉及到线程安全问题,得进行加锁操作,而该包下的类基于CAS实现count++来确保线程安全问题,就不需要进行加锁操作,提高了性能。

包下的类和使用:

3.2 实现自旋锁

4.CAS的ABA问题

4.1  什么是CAS的ABA问题

假设某一次CAS操作中value为A,此时和oldValue,如果判断相等就认为value没有被修改,但有可能该value被修改过(有其他线程从A改为B,再由B改为A).这就是ABA问题。

4.2  CAS的ABA问题引起的BUG

如出栈操作,刚开始栈类有节点A和节点B,进行线程一进行读取栈顶对old进行赋值,打算进行CAS(head,old,expect)操作就挂起等待,此时线程2进行读取进行CAS操作判断相等后进行pop和push一个新的节点A^,但A^的内存地址分配时刚好分配到和A一样的地址,push完之后线程1CAS操作判断相等,CAS操作成功,弹出A^,但用户并不知道,认为该弹出的是A.这是异常情况,正常情况为不相等,CAS操作失败,重新循环读取head到old重新CAS操作,相等后再进行pop真正弹出新的节点.

4.3解决方案

给要修改的值,引⼊版本号.在CAS⽐较数据当前值和旧值的同时,也要⽐较版本号是否符合预期.

• CAS操作在读取旧值的同时,也要读取版本号.

• 真正修改的时候,

如果当前版本号和读到的版本号相同,则修改数据,并把版本号+1.

◦ 如果当前版本号⾼于读到的版本号.就操作失败(认为数据已经被修改过了).

六.Callable接口

该接口也可以定义一个任务,线程执行任务时都是调用无返回值的run,但对run方法进行了封装,调用时封装后的可以返回值,方便程序员可以借助多线程的方式计算结果

举例:

总结创建线程的写法:

1.继承Thread类(定义单独的类/匿名内部类)

2.实现Runnable接口(定义单独的类/匿名内部类/lambda)

3.实现Callable

4.线程池

七.ReentrantLock类

作用:可以重入互斥锁,和synchronized关键字类似

1.ReentrantLock类下的方法:

lock()方法:获取锁,如果获取不到锁就会死等

trylock(时间)方法:获取锁,如果获取不到锁,等到超时间结束就放弃获取锁

unlock()方法:解锁

2.ReentrantLock类和synchronized的区别

1.synchronized是一个关键字,是基于JVM内部实现的(大概率基于C++实现的),ReentrantLock是Java标准库的一个类,是基于JVM外部实现的(Java代码实现的)

2.synchronized关键字在申请锁失败情况下会死等,而ReentrantLock提供了一个超时间的加锁方法,可以不死等。

3.synchronized一直都是非公平锁,ReentrantLock类也默认为非公平锁,但ReentrantLock提供了修改为公平锁的构造方法,只要创建实例时传入true就为公平锁。

4.synchronized关键字会自动释放锁,而ReentrantLock类必须通过类下的unlock方法进行解锁,一般容易遗漏,得搭配finally来使用

5.synchronized关键字唤醒锁是通过wait-notify来进行唤醒随机的一个线程,而RenntrantLock类搭配Condition类使用,可以精准唤醒某个线程

八.信号量Semaphore

信号量,也可以表示”可用资源的数量“,本质上是一个计数器。

作用:可以协调多个线程/进程之间的资源分配

使用:

利用可用资源被用完再申请资源可以设置可用资源为1,达到锁的效果:

九.CountDownLatch类

在多线程的使用中经常将一个大任务分成一个个小任务多线程执行,但何时任务全部完成呢?通过CountDownLatch类可以知道。

使用:

十.在多线程中使用线程不安全的类的解决办法

1.在多线程中使用ArrayList

1)自己使用同步机制(使用synchronized关键字ReentrantLock类

2)Collections.synchronizedList(new ArrayLsit)返回的List中的方法都是带有synchronized修饰的

3)使用CopyOnWriteArrayList类,该类不涉及加锁,但每次修改数据时都会复制存储数据的容器,在新的容器上增删改查,在复制过程中读取数据就会从旧的数据读取,复制成功之后把新容器的引用赋值给旧容器的引用(此操作为原子的),使引用指向新容器。

2.在多线程中使用哈希表

在多线程中使用HashMap是线程不安全的,但是使用Hashtable是线程安全的,但Hashtable给所有public修饰的方法中加以synchronized关键字修饰,以达到线程安全,效率比较低,于是对Hashtable进行了优化,提供了ConcurrentHashMap类。

http://www.dtcms.com/a/560566.html

相关文章:

  • 论文精读(七):结合大语言模型和领域知识库的证券规则规约方法
  • Linux shell sed 命令基础
  • 选 Redis Stream 还是传统 MQ?队列选型全攻略(适用场景、优缺点与实践建议)
  • 【JVM】详解 Java内存模型(JMM)
  • 做网站工作室广告网站建设
  • 小语种网站制作广州网站建设哪里有
  • 广州学做网站上饶网站建设多少钱
  • GO写的http服务,清空cookie
  • 响应式企业网站模板望京网站建设公司
  • 最新聊天记录做图网站ip软件点击百度竞价推广
  • 关于学校网站建设申请报告深圳市网络seo推广价格
  • 公司网站后台怎么上传图片百度西安分公司地址
  • Go语言设计模式:组合模式详解
  • 南昌市住房和城乡建设网站检测网站是否正常
  • 自建网站费用营销推广的主要方法
  • 罗田做网站一个人看的在线观看视频免费下载
  • 网站 首页 栏目 内容wordpress发文章
  • 云南建设厅和网站一个软件的制作过程
  • 湛江网站制作系统厦门哪些企业做视频网站的
  • 宝塔做网站安全吗网站建设课程设计要求
  • 建设微信网站制作自建购物网站
  • 网站的建设和推广上传网站教程
  • 怎么做网站关键字搜索超办网ppt下载
  • 杨凯做网站软件开发平台哪家好
  • 各大搜索引擎提交网站入口大全动漫网页设计作品模板
  • 优化大师怎么样seo优化一般多少钱
  • 设计师个人网站欣赏湖南企业竞价优化
  • 外贸网站建设wordpress的ping列表
  • 昆山高端网站建设咨询统一开发平台
  • 做网站要用什么语言网站建设干货图书