线程安全(有点乱哈)

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删除掉。

相关推荐
Yeniden2 分钟前
【设计模式】# 外观模式(Facade)大白话讲解!
java·设计模式·外观模式
脚踏实地的大梦想家2 分钟前
【Go】P17 Go语言并发编程核心:深入理解 Goroutine (从入门到实战)
java·开发语言·golang
Yeniden2 分钟前
【设计模式】 组合模式(Composite)大白话讲解
java·设计模式·组合模式
初学小白...7 分钟前
线程同步机制及三大不安全案例
java·开发语言·jvm
CS Beginner30 分钟前
【搭建】个人博客网站的搭建
java·前端·学习·servlet·log4j·mybatis
JavaTree20171 小时前
【Spring Boot】Spring Boot解决循环依赖
java·spring boot·后端
lang201509281 小时前
Maven 五分钟入门
java·maven
cj6341181501 小时前
SpringBoot配置Redis
java·后端
用坏多个鼠标2 小时前
Nacos和Nginx集群,项目启动失败问题
java·开发语言
满天星83035772 小时前
【C++】右值引用和移动语义
开发语言·c++·redis·visual studio