李林超博客
首页
归档
留言
友链
动态
关于
归档
留言
友链
动态
关于
首页
Java
正文
Java锁知识总结
Leefs
2020-03-06 AM
2912℃
1条
# Java锁知识总结 ### 前言 本篇在网上总结了一下关于Java锁的一些相关概念,希望可以给大家带来一点帮助 **1. 什么是线程安全,如何保证线程安全?** + 1.线程安全:就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。线程不安全就是不提供数据访问保护,有可能出现多个线程先后 更改数据造成所得到的数据是脏数据。 + 2.如何保证线程安全: + 2.1使用线程安全的类; + 2.2使用synchronized同步代码块,或者用Lock锁; + 2.3多线程并发情况下,线程共享的变量改为方法局部变量; **2. 产生死锁的四个条件** + 1.互斥:某种资源一次只允许一个进程访问,即该资源一旦分配给某个进程,其他进程就不能再访问,直到进程访问结束。 + 2.占有且等待:一个进程本身占有资源(一种或多种),同时还有资源未得到满足,正在等待其他进程释放该资源。 + 3.不可抢占:别人已经占有了某项资源,你不能因为自己也需要该资源,就去把别人的资源抢过来。 + 4.循环等待:存在一个进程链,使得每个进程都占有下一个进程所需的至少一种资源。 **3. volatile实现原理** 作用:使用volatile修饰的成员变量,就是告知程序任何对该变量的访问均需要从共享内存中获取,而对它的改变必须同步刷新回共享内存,它能保证所有线程对变量访问的可见性。 + 强制把修改的数据写回内存 + 在多处理器情况下使用多处理器缓存的数据失效 **4. synchronized实现原理** 作用:确保多个线程在同一个时刻,只能有一个线程处于方法或者同步块中,它保证了线程对变量访问的可见性和排他性。 原理:被synchronized修饰的代码区,当线程想进入的时候,须先获取对象监视器(相当于钥匙,只存在一把),获取对象监视器成功的进入修饰代码区,没有获取对象监视器的被阻塞在同步块和同步方法的入口处,进入BLOCKED状态。 ![Java锁知识总结(一)02.png][1] **5. synchronized作用与静态方法和非静态方法的区别?** + 非静态方法 给对象加锁(可以理解为给这个对象的内存上锁,只是这块内存,其他同类对象都会有各自的内存锁),这个时候在其他一个以上线程中执行该对象的这个同步方法就会产生互斥。 + 静态方法 相当于在类上加锁,位于代码区,静态方法位于静态区域,这个类产生的对象共用这个静态方法,所以这块内存有N个对象来竞争,这时候,只要是这个类产生的对象,在调用这个静态方法时会产生互斥。即该类所有的对象都共享一把锁。 **6. 当一个线程进入一个对象的synchronized方法A之后,其它线程是否可进入此对象的synchronized方法B?** 不能。其它线程只能访问该对象的非同步方法,同步方法则不能进入。因为非静态方法上的synchronized修饰符要求执行方法时要获得对象的锁,如果已经进入A方法说明对象锁已经被取走,那么试图进入B方法的线程就只能在等锁池(注意不是等待池哦)中等待对象的锁 **7. 线程同步的几种方式** + 1.synchronized修饰 + 2.`volataile`实现同步(只能保证可见性,不能保证原子性) + 3.使用局部变量 `ThreadLocal` + 4.用原子类(AtomicInteger、AtomicBoolean……) + 5.使用Lock + 6.使用容器类(BlockingQueue、ConcurrentHashMap) **8. Synchronized有哪些缺点?** synchronized无法中断一个正在等待获得锁的线程,也即多线程竞争一个锁时,其余未得到锁的线程只能不停的尝试获得锁,而不能中断。这种情况对于大量的竞争线程会造成性能的下降等后果。 **9. synchronized 与 lock 的区别** 1. 1.首先`synchronzied`是Java内置关键字,在JVM层面,Lock是个Java类; 2. 2.`synchronzied`无法判断是否获取锁的状态,Lock可以判断是否获取到锁 3. 3.`synchronzied`会自动释放锁,Lock需在finally中手工释放锁(lock.unlock()方法释放锁),否则容易造成线程死锁; 4. 4.用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2线程等待。如果线程1阻塞,线程2则会一直等待下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束了; 5. 5.synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可判断、可公平(两者皆可) 6. 6.Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题。 7. 7.Lock锁可以设置等待时间,到了时间自动放弃获取锁 详情可参考文章:[ReentrantLock和synchronized的比较](https://lilinchao.com/archives/667.html) **10. CAS无锁的概念、乐观锁和悲观锁** **概念**:CAS(compare and swap)是一种比较交换技术,可以用来鉴别线程技术,一旦检测到冲突就充当当前操作指导直到解决冲突。CAS机制中使用了3个基本操作数:内存地址V,旧的预期值A,要修改的新值B。更新一个变量的时候,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B。 **乐观锁**:大多基于版本来实现。将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为提交的数据是过期数据。 **悲观锁**:对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。 **11. 常见的原子操作类** `java.util.concurrent.atomic`包,这个包中的原子操作类,提供了一种用法简单,性能高效,线程安全的更新一个变量的方式。 `AtomicInteger、AtomicLong、AtomicBoolean、AtomicIntegerArray、AtomicReference(引用类型)、AtomicIntegerFieldUpdater(原子更新整形属性的更新器)` **12. 乐观锁的业务场景及实现方式** **业务场景**:适合读取操作比较频繁的操作。 **实现方式**:使用版本标识的方式来确定读到的数据和提交的数据是否一致。提交后修改版本标识,当检测出不一致时就丢弃或重试。 **13. 偏向锁、轻量级锁、重量级锁、自旋锁的概念** **偏向锁**:如果一个线程获得了锁,那么锁就进入了偏向模式。当这个线程再次请求锁时,无需再做任何同步操作。 **轻量级锁**:简单的将对象头部作为指针,指向持有锁的线程堆栈的内部,来判断一个线程是否持有对象锁。 **重量级锁**: **自旋锁**:轻量级锁就会膨胀为重量级锁后,虚拟机为了避免线程真实的在操作系统层面挂起,虚拟机还会在做最后的努力 *参考文章1:https://blog.csdn.net/hanliuxi4265/article/details/87971982* *参考文章2:https://www.cnblogs.com/lu51211314/p/10237154.html* [1]: https://lilinchao.com/usr/uploads/2020/03/726028496.png
标签:
并发编程
,
锁
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:
https://lilinchao.com/archives/698.html
上一篇
【转载】并发问题是怎样造成的
下一篇
Spring知识总结(一)
评论已关闭
栏目分类
随笔
2
Java
326
大数据
229
工具
31
其它
25
GO
47
NLP
4
标签云
Scala
Jquery
Java编程思想
GET和POST
MyBatis
JVM
Hbase
排序
Linux
Flume
SpringCloud
Filter
nginx
人工智能
Python
Thymeleaf
JavaWEB项目搭建
持有对象
数学
Golang
VUE
Docker
并发线程
Spring
Kibana
FileBeat
Jenkins
Golang基础
线程池
机器学习
友情链接
申请
范明明
庄严博客
Mx
陶小桃Blog
虫洞
评论已关闭