一:互斥
“同一时刻只有一个线程执行”这个条件非常重要,我们称之为互斥。如果我们能够保证对共享变量的修改是互斥的,那么, 无论是单核 CPU 还是多核 CPU,就都能保证原子性了。
二:锁的分类
1.悲观锁/乐观锁
悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为其他线程会修改,所以每次拿数据的时候都会加锁,其他线程只能等待,java里面的同步原语 synchronized关键字就是典型的悲观锁。
乐观锁:总是假设最好的情况,每次拿数据的时候认为不会有其他线程修改,所以不会加锁,但是在更新数据的时候会判断在此期间有没有其他线程更新了 这个数据(版本号机制),
如果修改了,则不做任何修改。乐观锁适用于读多写少的场景,可大大提高吞吐量。java并发包下的原子类正是基于乐观的一种方式 CAS(比较并交换实现的),通过CAS自旋实现原子操作的更新。
2.独享锁/共享锁
独享锁是指该锁同一时刻只能被一个线程所持有。
共享锁是指该锁可被多个线程所持有。
例如 synchronized ReentrantLock 是独享锁。
但对于ReadWriteLock,其写锁是独享锁,读锁是共享锁,读写,写读,写写互斥,可并发读。
3.可重入锁
可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。
synchronized ReentrantLock 都是可重入锁,可在一定程度上避免死锁。
4.公平锁/非公平锁
公平锁是指多个线