1.synchronized的作用:
解决多线程之间访问资源的同步性
(1)原子性:一个操作或者多个操作,要么全部执行不被打断,要么就不执行。(被synchronized修饰的类或者对象的所有操作都是原子,因为在执行操作之前会先获得该对象的锁,阻碍其他线程获得该对象,执行完毕后释放锁)
(2) 可见性:多个线程访问同一个资源时,该资源的状态对其他线程都是可见的。
(3)有序性:按照代码的先后顺序执行
2.synchronized的使用
1.修饰实例方法。(作用于当前对象实例加锁)
synchronized void method(){};
2.修饰静态方法。(给当前类加锁)
synchronized static void method(){};
3.修饰代码块。(给指定对象加锁)
synchronized(this){
}
3.sychronized锁升级
偏向锁-->轻量级锁-->重量级锁
偏向锁:仅有一个线程访问代码块,在对象头和栈帧中的所记录中存储该线程的id。这种锁资源耗用低。
轻量级锁:当sychronized为偏向锁时,当有其它线程访问,立刻升级为轻量级锁。这种锁的隔离性稍好,资源耗用任然不高,适用于多个线程访问但时间是错开的。这时,如果有线程访问则会产生锁自旋。
自旋:CAS,一种无锁算法,内有三个操作数,内存值V,旧的预期值A,要修改的新值B,
当且仅当旧的预期值=内存值时,将内存值修改为新值,否则重新为旧的预期值赋值为V,继续进行自旋。
重量级锁:当sychronized实现为一个轻量级锁时,一个线程持有锁,另一个线程要访问锁,产生锁自旋,当自旋数据达到jvm设定的上限,并且没有获得锁,就会升级为重量级锁。没有获得锁的线程一律阻塞。
4.synchronized原理
synchronized的实现依赖于特殊的cpu指令
synchronized同步语句块的实现使用了monitorenter和monitorexit,monitorenter指令指向同步代码块的开始位置,当执行了该指令后,线程尝试获取对象监控器(monitor)的所有权,加锁的本质就是得到monitor的所有权,monitorexit则是指向同步代码块的结束位置
sycnchronized修饰的方法并没有monitorenter和monitorexit,而是ACC-SYBCHRONIZED标识,该标识指明了该方法是一个同步方法,不过两者的本质都是对对象监控器minitor的获取