线程安全(有点乱哈)

1.多个进程访问共享资源,通过上锁保证数据安全

1.2锁的宏观分类方式是悲观锁和乐观锁

1.3悲观锁和乐观锁

悲观锁:拿数据上锁'

举例:synchronzied

乐观锁:每次拿数据的时候不会上锁,更新数据,比较下版本号'cas(一种缩写,一个方法,好像叫做compareandswap)

cas:compare and swap 即比较并替换

1.4锁相关的概念

2.synchronzied

悲观锁,一种同步锁

修饰代码块

修饰方法

修饰一个静态的方法 锁标识对象就是当前类字节码对象

this锁表示对象,多个线程要抢同一把锁,那么锁标识必须是同一个。

除了静态方法锁的是字节码对象,其余都是锁的this,锁标识对象。

2.1sysconnized原理

同步方法:vm使用ACC_SYNCHRONZIED标识实现,有标识,尝试获取monitor,然后执行方法,执行结束释放montor锁

同步代码块:monitoreter和monitoreit实现同步,monitoreter会获取对应的monitor

moniter有一个记录次数计数器,

退出,再自减,减到0别的线程就可以获取、

自己再获得+1

sys锁机制,1.5以前,通过cas指令,默认sys是重量级锁,1.6以后,对锁进行了升级,sys锁优化。

用户态:操作系统提供的一些api

内核态:cpu指令

同步方法和同步代码块过monitoreter实现

每个monitor都有一个对象

每一个锁标识对象都在堆里面有一个对象

对象头里有一个mark word 标识是轻量级锁还是重量级锁,指向结构体。

通过cas机制,判断_owner,为空,owner就是当前线程

count就是重复获取的次数,再次获取同一个线程

waitset 处于wait线程队列

entrylist:阻塞等待的线程

从entrylist中获取锁,获取到锁,owner变为抢到线程的id

释放锁:等着count减为0,释放锁,当count为0则将owner设置为null

2.2 1.6 以后锁的优化

锁清除:锁消除即删除不必要的加锁操作。根据代码逃逸技术,如果判断到一段代码中,堆上的数据不会逃逸出当前线程,那么可以认为这段代码是线程安全的,不必要加锁。

锁粗化

把锁扩大,不用每个都加,将连续的锁扩大为更大的锁。

锁的升级和降级

偏向锁:使cas记录获取它的线程,一个线程获取时,避免用户态转内核态

轻量级锁:是由偏向锁升级来的,第二个没有抢到就自旋等待(10ms以后尝试获取锁),某线程长时间等待,浪费资源。

重量级锁:锁竞争情况严重,由轻量级锁升级为重量级,某线程达到最大自旋次数10次,轻量级升级为重量级锁。

大部分都是在偏向锁和轻量级锁

3.线程并发库

线程并发库:比如显示锁,lock锁,juc简称,是专门java并发设计包

显示锁

需要自己显示的加锁

原子变量类(乐观锁)

为了实现原子性操作提供的原子类

线程池相关

并发容器类:concurentmap

同步工具类:倒计时门栓,countdownLatch,有个信号量

4.线程同步 lock

lock和sys的区别

它们都是悲观锁,都是jvm级别

lock是java代码实现的,api是显示锁,sys是jvm管理的,就是隐形锁

lock是显示锁,sys是内置锁

lock是一个接口,sys是一个关键字。

lock可公平可非公平

1.6之前,lock效率高于sys,1.6就差不多了。

sys可以修饰代码块,可以修饰方法。lock只能修饰代码块。

5.lock原理

先介绍,lock会用到的东西,一个unsafe类,一个AQS

unsafe类 ,不安全的操作,直接访问系统内存资源

先用反射获得,它会避免用户使用

做对内存的操作,cas操作,线程调度,这个unsafe类反正有点吊,可以阻塞线程,lock就会用到。

Lock基于AQS

AQS也只是个框架

构建锁和同步器的框架,底层用了cas技术保证

AQS原理分析

AQS底层原理,和sys底层原理一样。

state(0表示没有占用,可以占用) cas,尝试0设置为1,,失败就排列的等待。用park方法,放入队列,释放锁(和sys差不多),然后抢锁。

调用lock加锁的时候,用到了AQS,公平锁和非公平锁的方法

公平锁:比较尝试获取,cas了一下把计算器改为一(如果计算器等于0),成功把这个锁的当前设置为当前线程。失败,将计数器从0设置为1失败,当前持有锁的线程==当前线程,将计数器加1,如果等于,则是返回失败。、,阻塞然后放入等待队列。

释放线程:就是sys释放中大概意思,不过是用代码实现了

lock原理其实和sys原理差不多,不过sys是底层实现,lock代码实现,思路都可以说是一模一样,没有区别。

lock原理基于

7.线程安全乐观锁

是不加锁的,只是在修改的时候先做判断,有没有别人修改,atomic开头就是基于cas的乐观锁。

利用原子类

数据库通过version控制

工具类

countdownlatch(5) ,的值不为,则会一直阻塞,自己再新建个线程逻辑中减一。在分布式锁zookeeper中有用到,临时有序,每个监听前一个删除事件,删除了,就把它门栓设置为0。

信号量:多个线程竞争特定个数资源,做秒杀,限流(信号量限流)

8.TreadLocal,关于contoller变量对多并发的,太累了,就不写了。,其实还是加锁,不过这个效率高点。

它有一个map,每个线程都有一个map,

set值的话,默认是以当前作为key存入它底层的map的

存在一个内存泄漏的问题

entry是一个弱引用,有四种引用类型,强引用,软引用,和虚引用,关联到垃圾回收机制。

强引用:最常见的引用类型,只要存在,就不会被回收

软引用:内存不足时回收

弱引用:下次垃圾回收之前

虚引用:

强引入用在tl,map都被回收了,但是强引用没有被回收,这时导致内存泄漏,value成为一个永远无法被访问,无法被回收的对象。

treadloacl。声明为static final,还有remove删除掉。

相关推荐
摇滚侠3 分钟前
java http body的格式 ‌application/x-www-form-urlencoded‌不支持文件上传
java·开发语言·http
檀越剑指大厂13 分钟前
【Python系列】 Base64 编码:使用`base64`模块
开发语言·python
誓约酱17 分钟前
(动画)Qt控件 QLCDNumer
开发语言·c++·git·qt·编辑器
夫琅禾费米线17 分钟前
leetcode2650. 设计可取消函数 generator和Promise
开发语言·javascript·leetcode·ecmascript
@小博的博客28 分钟前
C++初阶学习第十三弹——容器适配器和优先级队列的概念
开发语言·数据结构·c++·学习
Dola_Pan31 分钟前
C语言:函数指针精讲
c语言·开发语言
尘浮生32 分钟前
Java项目实战II基于SpringBoot的共享单车管理系统开发文档+数据库+源码)
java·开发语言·数据库·spring boot·后端·微信小程序·小程序
2401_8574396937 分钟前
社团管理新工具:SpringBoot框架
java·spring boot·后端
凤枭香1 小时前
Python Scikit-learn简介
开发语言·python·机器学习·scikit-learn
ThetaarSofVenice1 小时前
Java从入门到放弃 之 泛型
java·开发语言