文章目录
一、JAVA中锁的概念
1、自旋锁
是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。
自旋锁有两种表现形式:
1、AtomicIneger 中的使用场景,自旋是为了修改一个变量,直接用CAS去进行操作
2、如下形式,通过自旋实现了一把锁
public class Demo2_SpinLock {
private AtomicReference<Thread> owner = new AtomicReference<Thread>();
public void lock() {
Thread current = Thread.currentThread();
// 利用CAS
while (!owner.compareAndSet(null, current)) {
// DO nothing
}
}
public void unlock() {
Thread current = Thread.currentThread();
owner.compareAndSet(current, null);
}
public static void main(String args[]){
Demo2_SpinLock lock = new Demo2_SpinLock();
lock.lock();
//do something
lock.unlock();
}
}
2、乐观锁
乐观锁不会让你的 线程阻塞、挂起 ,可以让CPU一直调度执行竞争这个乐观锁,可以直到成功为止。
如果竞争很激烈,导致乐观锁一直失败,那CPU就需要一直去调度他,但是又一直失败,就会有点浪费CPU的资源了。会导致CPU占用率飙高…………
假定没有冲突,在修改数据时如果发现数据和之前获取的不一致,则读最新数据,修改后重试修改。
3、悲观锁
悲观锁会在竞争锁资源失败后,直接 挂起、阻塞线程 ,等到锁资源释放后,才可能唤醒这个线程再去竞争锁资源。
假定会发生并发冲突,同步所有对数据的相关操作,从读数据就开始上锁。synchronized就是典型的悲观锁。
4、独享锁(写)
给资源加上写锁,线程可以修改资源,其他线程不能再加锁; (只能单个线程写)
5、共享锁(读)
给资源加上读锁后只能读不能改,其他线程也只能加读锁,不能加写锁; (可多个线程读)
应用场景:给数据库连接加说,限制数据库连接数量,同一时间只能有指定数量的连接,这个锁就是共享锁。