浅谈锁

33 篇文章 0 订阅
32 篇文章 0 订阅

1:首先我们为什么存在锁?这就要讲到多线程
单线程:就是指单个流水线的进程(A→B→C),这样的效率不太高
多线程:就像一句话所说:时间就想海绵里的水,挤挤总会有的,指多个单线程同时进行,效率高。资源得到充分的利用

2:其次我们就讲到两种状态:用户态和内核态
在初始的时候,一个应用程序和操作系统的是没有区分开来,也就是说app(也就是所谓的应用程序)可以将操作系统的工作控空间占用掉,导致操作系统运行某个程序运行着就拦停了,也即是说 一个应用程序可以直接干掉操作系统;但是现在作为一个应用程序来说很少能够干掉操作系统的,原因就是做了一个 分权处理; 把操作系统的权限给提高了,让咱们的 操作系统直接跟硬件打交道,去接受网络数据,去直接访问内存; 而我们的应用程序必须通过咱们的操作系统老大间接的支配咱们的硬件。JVM 就相当于我们应用程序,工作在用户态,也就是我们如果在java虚拟机中启动一个线程的话,操作系统内核必须的启动一个线程对应用户态的线程(1:1的关系),(拓展:M:1或者就是M:N(go语言的协程);纤程,我们也称为用户态线程,轻量级线程); jdk1.0,jdk1.1,jdk1.2版本的时候,我们的synchronized使用的是重量级锁,也就是说在争抢锁的过程中是要调用操作系统老大这个角色;切换线程的速度比较的慢;在jdk1.6之后,synchronized在jvm中有一个锁升级过程,就一般不会去调用os这个老大,也就加快了线程之间的切换速度

总结: 操作系统工作的在内核态,应用程序工作在用户态,这样的工作状态是的操作系统更加的安全

3:锁状态

3.1:重量级锁:内核态说白了就是自己实在四解决不了就得需要调用操作系统老大
3.2:轻量级锁也称作自旋锁:用户态说白了就是自己就可以解决,所以就不需要去调用操作系统,速度比较的快
3.3:偏向锁:用户态线程在大多数情况下并不存在竞争条件,使用同步会消耗性能,而偏向锁是对锁的优化,可以消除同步,提升性能。当一个线程获得锁,会将对象头的锁标志位设为01,进入偏向模式.偏向锁可以在让一个线程一直持有锁,在其他线程需要竞争锁的时候,再释放锁
3.4:无锁:对象没有加锁

4:对象在内存中的布局
在这里插入图片描述

5:synchronized锁升级过程
在这里插入图片描述

在这里插入图片描述
总结:

1:当我们创建一个对象的时候是处于无锁态的
2:当我们new一个对象出来的时候,要给他进行加锁,这个过程中是有一个锁升级的过程
3:偏向锁:会偏向第一个线程(把自己的线程id放到对象头中),内有争抢(锁竞争)的过程
4:轻量级(自旋)锁:当另外一或者n个线程过来进行抢锁,我们的解决方案就是把 偏向锁取消,然后线程同时进行抢锁(谁抢到算谁的),但是这个时候并不是在内核态(里面有个线程等待队列(闲等待:等着OS来叫你),谁抢到谁用,没有抢到的继续放回等待队列)进行竞争,而是在用户态进行自旋竞争(忙竞争:也就是别进等待队列,让他在在进行自旋CAS:一个死循环去判断是不是还是刚开始取出来的那个值)
5:重量级锁:也就是当一个线程霸占的时候,其他线程在自旋等待的话,是会消耗CPU的,浪费了CPU的资源;
6:结论1: 所以说长时间的锁定是不建议用自旋锁的
7:结论2: 所以说等待线程超级多的时候不适合自旋锁
8::结论3: 所以说凡是发生有结论1和结论2的情况,我们就将轻量级(自旋)锁,升级为重量级锁
9:到底什么时候升级?我们用两个参数(1:线程等待的数量;2:等待的时候超过多长);在jdk1.6之前,我们执行10次自旋,就升级为重量级锁;等待线程数超过CPU和数的1/2,就升级为重量级锁

扩展:

1:小端:把最低位的字节放在最前面(一般我们电脑上表现数字都是使用的是小端)
2:大端:把最低位的字节放在最后面(大端一般适用于网络传输)
3:在CAS中怎么解决ABA问题:我们提出的解决方法就是去引入版本号
4:在CAS中它本身也是需要具有原子性的,在这个底层就是C/C++实现的,里面有条原语(直接控制CPU的指令)lock_if_mp是进行 锁住总线,因为在多核CPU的情况下是通过总线去访问内存空间的
5:自旋锁是在用户态进行自旋的,是会消耗CPU的,但是等待队列是在内核态是不会消耗CPU的

6:常见的多线程加锁机制类型及区别和共同点

1:synchronized
2:Reentrantlock
1:共同点:两个都是可重入锁;
“可重入锁”概念是:自己可以再次获取自己的内部锁。比如,一个线程获得了某个对象的锁,此时这个对象锁还没有释放,当其再次想要获取这个对象的锁时,还可以再获取的;如果不可锁重入的话,就会造成死锁;同一个线程每次获取锁,锁的计数器都自增1,所以要等到锁的计数器下降为0时,才能最终释放锁。
2:区别:synchronized 依赖于 JVM,而 ReentrantLock 依赖于 API
2.1:synchronized 是依赖于 JVM 实现的,Java 虚拟机团队在 JDK1.6 为 synchronized 关键字进行了很多的优化,但这些优化都是在虚拟机层面实现的,并没有直接暴露给我们。ReentrantLock 是 JDK 层面实现的(也就是 API 层面,需要 lock() 和 unlock() 方法配合 try/finally 语句块来完成),可以通过查看它的源代码,来看它是如何实现的
2.2: ReentrantLock 比 synchronized 增加了一些高级功能;主要有三点:① 等待可中断(正在等待的线程可以选择放弃等待,改为处理其他事情);② 可实现公平锁(先等待的线程最先获得锁);③ 可实现选择性通知(锁可以绑定多个条件)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值