使用场景
一、volatile:
(1) 一个变量被一个线程更改后,其它线程能立即知道。主要用来修饰被不同线程访问和修改变量。
(2) 变量在多个线程中安全的前提是变量修改方式的原子性即简单的读取、赋值 。
例如1:变量n,在线程中执行n++(n++ 和 n = n+1 对n值的改变包括3个操作:读取 n 的值,进行加 1 操作,写入新的值),不具有原子性
例如2:变量n,在线程中执行n=p(p = n+1 n=p,对n值的改变包括2个操作:读取 p 的值,赋值给n),具有原子性
示例:
private volatile int age = 0;
二、synchronized
(1) 可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。然而,当一个线程访问object的一个加锁代码块时,另一个线程仍然可以访问该object中的非加锁代码块。
例如:
public synchronized void synMethod(){
//方法体
}
(2)synchronized是悲观锁
乐观锁
乐观锁是一种乐观思想,即认为读多写少,遇到并发的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,采取在写时先读取当前版本号,然后加锁操作(比较跟上一次的版本号,如果一样则更新)
java中的乐观锁基本都是通过CAS操作实现的,CAS是一种更新的原子操作,比较当前值跟传入值是否一样,一样则更新,否则失败。
悲观锁
悲观锁就是一种悲观思想,即认为写多读少,遇到并发的可能性高,每次去拿数据都会认为数据被别人修改了,所以每次都需要加锁,这样别人想读写这个数据就会block知道拿到锁,java中的悲观锁就是Synchronized。
参考: