java锁

synchronized(重量级)和ReentrantLock(轻量级) 重入锁 都具有可重入性
读写锁(lock)-轻量级

悲观锁和乐观锁
乐观锁:本质没有锁,效率比较高、无阻塞、无等待、重试。—CAS无锁机制
总是认为不会产生并发问题,每次去取数据的时候总认为不会有其他线程对数据进行修改,因此不会上锁,但是在更新时会判断其他线程在这之前有没有对数据进行修改,一般会使用版本号机制或CAS操作实现。

version方式:一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功。
核心SQL语句
update table set x=x+1, version=version+1 where id=#{id} and version=#{version};
SQL解读:
如果同时进来两条线程,传入id和version去查询数据。如果可以查到数据,那么说明这条数据没有被修改。
如果查询不到数据,则说明此数据已被修改。不能继续对该id数据进行处理

CAS操作方式:即compare and swap 或者 compare and set,涉及到三个操作数,数据所在的内存值,预期值,新值。当需要更新时,判断当前内存值与之前取到的值是否相等,若相等,则用新值更新,若失败则重试,一般情况下是一个自旋操作,即不断的重试。

悲观锁
重量级锁
总是假设最坏的情况,每次取数据时都认为其他线程会修改,所以都会加锁(读锁、写锁、行锁等),当其他线程想要访问数据时,都需要阻塞挂起。可以依靠数据库实现,如行锁、读锁和写锁等,都是在操作之前加锁,在Java中,synchronized的思想也是悲观锁。

CAS无锁
cas由自旋实现的,不能说自旋就是cas
compare and swap或者compare and set,涉及到三个操作数,数据所在的内存值、预期值、新值。当需要更新时,判断当前内存值与之前取到的值是否相等,若相等,则用新值更新,若失败则重试,一般情况下是一个自旋操作,即不断的重试
在这里插入图片描述
循环刷新的过程是一个死循环处理,当变量值等于预期值的时候,跳出循环。赋值给新值。
无锁的好处无锁的好处:
第一,在高并发的情况下,它比有锁的程序拥有更好的性能;
第二,它天生就是死锁免疫的
缺点:
问题:如果变量V初次读取的时候是A,并且在准备赋值的时候检查到它仍然是A,那能说明它的值没有被其他线程修改过了吗?

如果在这段期间曾经被改成B,然后又改回A,那CAS操作就会误认为它从来没有被修改过。针对这种情况,java并发包中提供了一个带有标记的原子引用类AtomicStampedReference,它可以通过控制变量值的版本来保证CAS的正确性。
自旋锁
由于自旋锁使用者一般保持锁时间非常短,因此选择自旋而不是睡眠是非常必要的,自旋锁的效率远高于互斥锁。
如何旋转呢?何为自旋锁?
就是如果发现锁定了,不是睡眠等待,而是采用让当前线程不停地在循环体内执行实现的,当循环的条件被其他线程改变时,才能进入临界区。

自旋锁和互斥锁(sychronized)的区别?
1、互斥锁需要等待、阻塞,效率比较低
2、自旋锁只是在循环体内执行,效率较高

互斥锁:线程会从sleep(加锁)——>running(解锁),过程中有上下文的切换,CPU的抢占,信号的发送等开销。
自旋锁:线程一直是running(加锁——>解锁),死循环检测锁的标志位,机制不复杂。

AQS
分布式锁—Redis实现分布式锁、zookeeper实现分布式锁
非公平锁、公平锁
非公平锁:在等待锁的过程中,如果有任意新的线程妄图获取锁,都是有很大的几率直接获取到锁的。
公平锁:每次都是一次从队首取值

公平和非公平锁的队列都基于锁内部维护的一个双向链表,表节点Node的值就是每一个请求当前锁的线程。

白话文理解:公平锁是先到先得,按序进行,非公平锁就是不排队直接拿,失败再说

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值