锁
引用: https://blog.youkuaiyun.com/renwei289443/article/details/79540809
- CAS
无锁的执行者,比较与交换用于实现多线程中同步的原子指令。将内存中的内容与定值比较,只有相同,才将内存内容修改。原子性保证新值基于最新信息计算; 如果该值在同一时间被另一个线程更新,则写入将失败。 操作结果必须说明是否进行替换; 这可以通过一个简单的布尔响应(这个变体通常称为比较和设置),或通过返回从内存位置读取的值来完成 - 乐观锁与悲观锁
悲观锁:竞争总会发生,每次拿到数据都上锁,共享资源每次只给一个线程使用,其他线程阻塞,用完后才把资源给其他线程。,关系型数据库常见,Synchronized、ReentrantLock也是。
乐观锁:竞争永不发生,不上锁。但是在更新的时候会判断别人有没有更新这个数据(版本号机制,CAS算法),用于多读程序,提高吞吐量,write_condition。出现ABA问题。变量初始值与最后该线程的写入值相同,不代表它没有改动过。 - 分布式锁,偏向锁,轻量级锁,重量级锁,monitor
根据竞争进行升级:
偏向锁:为线程获得锁的代价降低,只允许一个线程获得锁,无竞争时使用。先根据标识位结合epoch判断状态,若为可偏向状态,进行CAS,CAS成功,则获取偏量锁进行同步代码。否则升级为轻量级锁。当超过一个线程竞争一个对象时,会出现偏向锁撤销操作。
轻量级锁:允许按顺序的多个程序获得锁,轻度竞争,识别为不可以偏见的无锁状态,进行CAS操作,将对象头的Mark Word替换为指向锁的锁记录指针,如果替换成功,获得锁,若不成功,自旋争抢锁,还不得升级为重量级锁。
重量级锁:重度竞争
分布式锁:在分布式模型下,数据只有一份(限制),需要锁技术控制某一时刻修改数据的进程数。
Monitor:管程,变成语言,在语法的基础上提供语法糖,同一时刻,只有一个进程/线程能进入monitor临界区,达到互斥,没有进入临界区的进程/线程被注册,必要的时候会被唤醒。属于一个同步工具。 - 锁优化,锁消除,锁粗化,自旋锁,可重入锁。
锁优化:减少锁的时间,能不放同步代码块的就不放;锁拆分,并行锁,降低锁竞争(减少粒度,ConcurrentHashMap)
锁粗化:循环内的操作加锁,那么应该把锁放到循环外,增加锁粒度。
可重入锁:解决自己持有锁的时候,再次判断是否资源被占有时。自旋锁是不可重入锁。
自旋锁:让当前线程不停在循环体中执行,当循环条件被其他线程改变时才进入临界区。
锁消除:线程私有,同步加锁无需要。
public class Demo {
public Object obj = new Object();
public static synchronized void method1() { //1.静态同步函数,使用本类字节码做类锁(即Demo.class)
}
public void method2() {
synchronized (Demo.class) { //同步代码块,使用字节码做类锁
}
public synchronized void method3() { //同步函数,使用本类对象实例即this做对象锁
}
public void method4() {
synchronized (this) { //同步代码块,使用本类对象实例即this做对象锁
}
public void method5() {
synchronized (obj) { //同步代码块,使用共享数据obj实例做对象锁。
}
}
}