文章目录

  • 一、悲观锁
  • 二、乐观锁
  • 三、乐观锁 CAS 三大问题

一、悲观锁


假设有 222 个线程 , 线程 A 和 线程 B ; 线程 A 访问共享资源 , 线程 B 等待 , 一旦线程 A 访问结束 , 线程 B 访问该共享资源 ;

悲观锁 : 只要有 线程 来操作 共享资源 , 就认为肯定 有其它若干线程也要操作该共享资源 , 一定要 对共享资源进行加锁 ; 任何情况下 , 哪怕 只有一个线程访问共享资源 , 也要对该共享资源进行加锁 ; ( 持有悲观的态度 )

对共享资源加锁 , 会对该资源产生负面影响 , 效率会降低 ;

如果只是 单线程访问资源 , 不会产生并发问题 , 没有必要进行加锁 ; 如果加了锁 , 执行效率变低 , 造成了资源浪费 ;

synchronized 就是悲观锁 ;

二、乐观锁


乐观锁 : 持有乐观的态度 , 线程 A 访问共享资源 , 乐观的认为只有 111 个线程访问该资源 , 不用进行加锁 ;

线程 A 访问主内存变量前 , 记录下值 XXX , 线程 A 访问完毕后 , 会将最终的值同步到主内存中 , 此时会检查下 主内存中变量的值是否还是 XXX ,

  • 如果是 , 则说明 线程 A 访问期间 没有线程修改该变量值 , 那么将线程 A 计算的 新值更新到主内存中
  • 如果不是 , 主内存中的变量值变成了 YYY , 那么说明该值 被其它线程修改了 ; 那么将当前值抛弃 , 重新从主内存获取变量值 YYY , 然后线程 A 继续执行 , 执行完毕后将计算结果同步到主内存变量中 , 再次对比主内存中的变量值是否是 YYY , 如果是可以更新 , 如果不是 , 那么再次重复本操作 ;

乐观锁 , 全程没有加锁 , 没有阻塞 , 只要判定主内存中被访问的共享变量 , 线程计算之前的值与计算之后的值一致 , 就更新到主线程中 ;

三、乐观锁 CAS 三大问题


CAS : Compare and Swap , 比较再交换 , 是乐观锁中的线程访问完共享变量后 , 先进行变量比较 , 然后在同步共享变量值 ;

JDK 1.51.51.5 之后提供的 java.util.concurrent 包中的类 , 解决了 CAS 相关问题 ;

java.util.concurrent 包简称 J.U.C ;

CAS 解决的 333 大问题 :

ABA 问题 :

  • 问题描述 : 线程 A 访问变量 X = 0 , 访问期间 , 线程 B 访问 X 将其改为 1 , 然后 线程 C 访问 X 将其又改为 0 , 此时线程 A 访问完毕后 , 查询发现变量 X 仍然是 0 , 认为期间没有线程访问该变量 ;
  • 解决方案 : 给变量设置一个版本号 , 每次线程访问变量时 , 版本号 +1 , 这样每次判断变量的版本号即可 ;

循环时间过长 :

  • 问题描述 : 乐观锁中 , 假如连续多次写回数据时 , 发现值改变 , 校验失败 , 导致 重复执行线程代码 , 会给 CPU 带来很大开销 , 这些 CPU 时间片都浪费了 ;
  • 解决方案 : 将锁升级 ;

保证多个共享变量原子性问题 :

  • 问题描述 : 针对 单个共享变量 访问时 , 使用 atomic 原子类 可以使用 CAS 保证原子操作 , 如果 有多个共享变量 , CAS 无法保证操作的原子性 ;
  • 解决方案 : 使用 JDK 提供的 AtomicReference 封装多个变量到一个类对象中 , 保证共享变量的原子性 ;

线程 A 访问共享变量的操作 , 不是原子操作 , 就会导致如下问题 :

线程 A 访问变量 X , 执行完毕后 , 变量 X 值原始值进行比较 , 比较相等 , 将数据更新到主内存 , 如果在 比较相等后 , 在 数据更新到主内存之前 , 有 另外一个线程 B 修改了该变量 X , 这样就出现了问题 ;

【Java 并发编程】线程锁机制 ( 悲观锁 | 乐观锁 | CAS 三大问题 | ABA 问题 | 循环时间长问题 | 多个共享变量原子性问题 )相关推荐

  1. Java 并发编程 -- 线程池源码实战

    一.概述 小编在网上看了好多的关于线程池原理.源码分析相关的文章,但是说实话,没有一篇让我觉得读完之后豁然开朗,完完全全的明白线程池,要么写的太简单,只写了一点皮毛,要么就是是晦涩难懂,看完之后几乎都 ...

  2. 判断线程是否执行完毕_Java并发编程 | 线程核心机制,基础概念扩展

    源码地址:GitHub || GitEE 一.线程基本机制 1.概念描述 并发编程的特点是:可以将程序划分为多个分离且独立运行的任务,通过线程来驱动这些独立的任务执行,从而提升整体的效率.下面提供一个 ...

  3. Java并发编程—线程间协作方式wait()、notify()、notifyAll()和Condition

    原文作者:Matrix海 子 原文地址:Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 目录 一.wait().notify()和notifyA ...

  4. 【Java并发编程】:使用synchronized获取互斥锁

    在并发编程中,多线程同时并发访问的资源叫做临界资源,当多个线程同时访问对象并要求操作相同资源时,分割了原子操作就有可能出现数据的不一致或数据不完整的情况,为避免这种情况的发生,我们会采取同步机制,以确 ...

  5. Java并发编程实战————可重入内置锁

    引言 在<Java Concurrency in Practice>的加锁机制一节中作者提到: Java提供一种内置的锁机制来支持原子性:同步代码块."重入"意味着获取 ...

  6. Java并发编程实战 第13章 显式锁

    接口Lock的实现类: ReentrantLock, ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock Reentra ...

  7. Java并发编程:Synchronized底层优化(偏向锁、轻量级锁)

    一.重量级锁 上篇文章中向大家介绍了Synchronized的用法及其实现的原理.现在我们应该知道,Synchronized是通过对象内部的一个叫做监视器锁(monitor)来实现的.但是监视器锁本质 ...

  8. Java并发编程-线程安全基础

    线程安全基础 1.线程安全问题 2.账户取款案例 3.同步代码块synchronized synchronized的理解 java中有三大变量的线程安全问题 在实例方法上使用synchronized ...

  9. Java并发编程——线程池的使用

    在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统 ...

最新文章

  1. Go 学习笔记(26)— Go 习惯用法(多值赋值,短变量声明和赋值,简写模式、多值返回函数、comma,ok 表达式、传值规则)
  2. [LeetCode]--290. Word Pattern
  3. oracle数据库应用与开发习题,《Oracle数据库应用》练习题及答案.docx
  4. 外设驱动库开发笔记14:DS18B20温度变送器驱动
  5. 服务器客户端对话java_java中的服务器和客户机如何使用
  6. HttpClient 教程 (六)
  7. python aiompq集群_python操作memcached以及分布式
  8. 柱底反力求和lisp软件_基于AutoLisp语言的RC异形柱下独立基础验算方法与流程
  9. 『ORACLE』 Linux和oracle用户下的常用命令(11g)
  10. 基于AIML2.0写一个机器人
  11. 银行保险机构信息科技外包风险管理办法学习笔记
  12. CodeForces1036 F Relatively Prime Powers(莫比乌斯容斥)
  13. 永远的7日之都怎么在电脑上玩 永远的7日之都安卓模拟器教程
  14. uniapp 微信小程序修改BarTitle
  15. java 雷达反射面积_请问:如何使用基本反射率雷达图中的dBZ值判断天气情况?比如多云、雷雨、晴等。谢谢!...
  16. 28岁转行程序员?别想了、没戏。事实真就如此残酷?
  17. 怎么完成一个无尽的长列表
  18. 梦幻西游热门服务器卡顿延迟,梦幻西游:周末活动卡顿的最总原因,是人真的多还是服务器问题?...
  19. window 删除文件提示指定的文件名无效或太长
  20. mpmath.psi python_Mol Cell Proteomics. |马臻| psims-一个用于编写HUPO-PSI标准下的mzML和mzIdentML的python库...

热门文章

  1. JAVA构造方法,继承关系和SUPER关键字
  2. Android NDK: WARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 8
  3. 类别继承-程序代码再用
  4. 命名式ACL配置实例
  5. Python爬虫(十一)_案例:使用XPath的爬虫
  6. [转载]秀脱linux实战笔记linux-kernel-3.0.3实战篇
  7. Kotlin学习-基础知识点
  8. Android 透明度百分比对应的 十六进制
  9. freebsd 域名服务器
  10. 微信 WEUI 的 switch button 精简提取