Java各种锁机制简述
线程安全是多线程领域的问题,线程安全可以简单理解为一个方法或者一个实例可以在多线程环境中使用而不会出现问题。
在 Java 多线程编程当中,提供了多种实现 Java 线程安全的方式:
- 最简单的方式,使用
Synchronization
关键字 - 使用
java.util.concurrent.atomic
包中的原子类,例如AtomicInteger
- 使用
java.util.concurrent.locks
包中的锁 - 使用线程安全的集合
ConcurrentHashMap
- 使用
volatile
关键字,保证变量可见性(直接从内存读,而不是从线程cache
读
volatile 实现原理
- 在 JVM 底层 volatile 是采用“内存屏障”来实现的
- 缓存一致性协议(MESI协议)它确保每个缓存中使用的共享变量的副本是一致的。其核心思想如下:当某个 CPU 在写数据时,如果发现操作的变量是共享变量,则会通知其他 CPU 告知该变量的缓存行是无效的,因此其他 CPU 在读取该变量时,发现其无效会重新从主存中加载数据
synchronize 实现原理
同步代码块是使用 monitorenter
和 monitorexit
指令实现的,同步方法(在这看不出来需要看 JVM 底层实现)依靠的是方法修饰符上的 ACC_SYNCHRONIZED
实现。
CAS 乐观锁
CAS 是项乐观锁技术,当多个线程尝试使用 CAS 同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。
CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。无论哪种情况,它都会在 CAS 指令之前返回该位置的值。(在 CAS 的一些特殊情况下将仅返回 CAS 是否成功,而不提取当前值。)CAS 有效地说明了“我认为位置 V 应该包含值 A;如果包含该值,则将 B 放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。”这其实和乐观锁的冲突检查 + 数据更新的原理是一样的。
ABA 问题
CAS 会导致“ABA问题”。
CAS 算法实现一个重要前提需要取出内存中某时刻的数据,而在下时刻比较并替换,那么在这个时间差类会导致数据的变化。
比如说一个线程 one 从内存位置 V 中取出 A,这时候另一个线程 two 也从内存中取出 A,并且 two 进行了一些操作变成了 B,然后 two 又将 V 位置的数据变成 A,这时候线程 one 进行 CAS 操作发现内存中仍然是 A,然后 one 操作成功。尽管线程 one 的 CAS 操作成功,但是不代表这个过程就是没有问题的。
部分乐观锁的实现是通过版本号(version)的方式来解决 ABA 问题,乐观锁每次在执行数据的修改操作时,都会带上一个版本号,一旦版本号和数据的版本号一致就可以执行修改操作并对版本号执行 +1 操作,否则就执行失败。因为每次操作的版本号都会随之增加,所以不会出现 ABA 问题,因为版本号只会增加不会减少。
乐观锁的业务场景及实现方式
乐观锁(Optimistic Lock):
- 每次获取数据的时候,都不会担心数据被修改,所以每次获取数据的时候都不会进行加锁,但是在更新数据的时候需要判断该数据是否被别人修改过。如果数据被其他线程修改,则不进行数据更新,如果数据没有被其他线程修改,则进行数据更新。由于数据没有进行加锁,期间该数据可以被其他线程进行读写操作。
- 比较适合读取操作比较频繁的场景,如果出现大量的写入操作,数据发生冲突的可能性就会增大,为了保证数据的一致性,应用层需要不断的重新获取数据,这样会增加大量的查询操作,降低了系统的吞吐量。
Java各种锁机制简述的更多相关文章
- Java的锁机制--synchronsized关键字
引言 高并发环境下,多线程可能需要同时访问一个资源,并交替执行非原子性的操作,很容易出现最终结果与期望值相违背的情况,或者直接引发程序错误. 举个简单示例,存在一个初始静态变量count=0,两个线程 ...
- java的锁机制
一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在Java里边就是拿到某个同步对象的锁(一个对象只有一把锁): 如果这个时候同步对象的锁被其他线程拿走了,他(这个线 ...
- Java常用锁机制简介
在开发Java多线程应用程序中,各个线程之间由于要共享资源,必须用到锁机制.Java提供了多种多线程锁机制的实现方式,常见的有synchronized.ReentrantLock.Semaphore. ...
- lesson3:java的锁机制原理和分析
jdk1.5之前,我们对代码加锁(实际是对象加锁),都是采用Synchronized关键字来处理,jdk1.5及以后的版本中,并发编程大师Doug Lea在concurrrent包中提供了Lock机制 ...
- 深入浅出 Java Concurrency 锁机制 : AQS
转载:http://www.blogjava.net/xylz/archive/2010/07/06/325390.html 在理解J.U.C原理以及锁机制之前,我们来介绍J.U.C框架最核心也是最复 ...
- [java多线程] - 锁机制&同步代码块&信号量
在美眉图片下载demo中,我们可以看到多个线程在公用一些变量,这个时候难免会发生冲突.冲突并不可怕,可怕的是当多线程的情况下,你没法控制冲突.按照我的理解在java中实现同步的方式分为三种,分别是:同 ...
- java的锁机制——synchronized
一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在java里边就是拿到某个同步对象的锁(一个对象只有一把锁): 如果这个时候同步对象的锁被其他线程拿走了,他(这个线 ...
- [置顶] 深入探析Java线程锁机制
今天在iteye上提了一个关于++操作和线程安全的问题,一位朋友的回答一言点醒梦中人,至此我对Java线程锁有了更加深刻的认识.在这里也做个总结供大家参考. 先看几段代码吧! 代码一: public ...
- Java 线程锁机制 -Synchronized Lock 互斥锁 读写锁
(1)synchronized 是互斥锁: (2)ReentrantLock 顾名思义 :可重入锁 (3)ReadWriteLock :读写锁 读写锁特点: a)多个读者可以同时进行读b)写者必须互斥 ...
随机推荐
- golang 标准库 sync.Map 中 nil 和 expunge 区别
本文不是 sync.Map 源码详细解读,而是聚焦 entry 的不同状态,特别是 nil 状态和 expunge 状态的区分. entry 是 sync.Map 存放值的结构体,其值有三种,分别为 ...
- IntlliJ IDEA 注册码获取或离线破解
JB 的软件还是挺好用的,建议有钱的话支持正版.. IntelliJ IDEA 有开源版,但是要想玩企业级开发,还是得用收费版. 不管哪种方式,使用前都需要把"0.0.0.0 account ...
- laravel 中 同个主域名下,多个项目共享session登录状态
共享session的前提是session在一个公共的地方,比如database,redis等,laravel框架提供了很大驱动选择: 这里只需要在配置文件里配置三个地方即可 'driver' => ...
- c++ 读取 utf-8 文件到 string
#include <iostream> #include <assert.h> #include <fstream> #include <string> ...
- text获取元素的文本
1断言 代码 # -*-coding:utf-8-*-from selenium import webdriverimport time as tdriver = webdriver.Chrome() ...
- PIL实现图片框架以及生成图片验证码
1. PIL的基本概念 PIL:即Python Imaging Library,是Python平台事实上的图像处理标准库. PIL中涉及通道(bands)和模式(mode)这两个重要概念. (1)通道 ...
- django中使用原生的orm
只有用的时候才能执行
- debian上安装mysql server
1 将mysql添加到apt的repository中 第一步,下载mysql提供的ppa文件 wget https://dev.mysql.com/get/mysql-apt-config_0.8.1 ...
- Windows上Tomcat安装以及解决乱码问题
Windows上Tomcat安装以及解决乱码问题 下载tomcat8 1.进入tomcat官网 官方网站 2.选择windows的版本 解压 确定自己配置好了jdk jdk的相关配置 配置好tomca ...
- onehot编码解释
什么是One-Hot编码? One-Hot编码,又称为一位有效编码,主要是采用N位状态寄存器来对N个状态进行编码,每个状态都由他独立的寄存器位,并且在任意时候只有一位有效. One-Hot编码是分类变 ...