锁、分布式锁、无锁分布式无锁
为什么要有锁?
保证资源线程安全,简单说就是在多线程情况下不会乱。
锁的分类
- JVM锁:类锁、对象锁、偏向、公平、重入、死锁
- 分布式锁:Redis、DB、zookeeper
类锁和对象锁的区别
类锁
- 方法中写着static synchronized
- 整个Object.class只有一个锁,所有对象只有一个锁
对象锁
- 方法声明中只写synchronized
- Object的实例化对象object1、object2、object3,各有一个自己的锁
JVM锁如何实现
同步方法
public synchronized void save(){}
注: synchronized关键字也可以修饰静态方法,此时如果调用该静态方法,将会锁住整个类
同步块
synchronized(object){
}
注:同步是一种高开销的操作,因此应该尽量减少同步的内容。
volatile
- volatile关键字为域变量的访问提供了一种免锁机制,
- 使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新,
- 因此每次使用该域就要重新计算,而不是使用寄存器中的值
- volatile不会提供任何原子操作,它也不能用来修饰final类型的变量
注:这个虽然能实现线程安全,但是没有原子性,如(i++)
重入锁:ReenreantLock
- ReentrantLock() : 创建一个ReentrantLock实例
- lock() : 获得锁
- unlock() : 释放锁
注:ReentrantLock()还有一个可以创建公平锁的构造方法,但由于能大幅度降低程序运行效率,不推荐使用
并发集合、并发工具类
- ConcurrentHashMap
- CopyOnWriteArrayList
- 并发工具类:java.util.concurrent(JUC)
原子操作:Atomic
使用局部变量实现线程同步:ThreadLocal
分布式锁
Redis
- 单线程,速度快,单点
- 加锁:setNx()、取锁:getNx()
- 或者setString也可以实现分布式锁
DB
悲观锁:select * from table for update(Quartz)
乐观锁:加多个version字段
Zookeeper:待学习。。。。。
无锁、分布式无锁
同样是使用redis实现,用它的自增功能,jedis.incr()