原理
synchronized一般用于加锁,可以针对方法
和代码块
进行加锁。
流程如下:
当某个线程要访问某个方法或代码块时
检查ACC_SYNCHRONIZED标志,如果有设置,那么尝试获取监视器monitor锁
获取锁成功,开始执行方法,执行完成后释放监视器monitor锁
获取锁成功,但内部发生异常,没有处理异常时,默认释放monitor锁,并且向外抛出异常
获取锁失败,阻塞等待。
monitor锁
使用monitorenter指令进行加锁
使用monitorexit指令释放锁
当线程获取到锁时,计数器加1,当释放锁时,计算器减1
当计数器为0时,线程可以获取到锁
特性
互斥性
阻塞性
可重入
锁的是什么
public void synchronized test(){}
锁的是调用该方法的实例对象
public static void synchronized test(){}
锁的是该方法归属的类的对象
synchronized(this){}
锁的是this的实例对象
synchronized(Test.class){}
锁的是Test类对象
如何保证原子性
synchronized通过monitorenter和monitorexit两个指令实现加锁和解锁,由于synchronized是可重入的,当线程工作时,即使cpu时间片切换,下一次获取到cpu时间片的还是当前线程,因此其他线程在该线程没有释放锁时是无法获取到锁的
如何保证有序性
在单节点中,被synchronized修饰的代码只能被1个线程所访问,即:单线程执行的。在单个线程中执行的程序代码都是天然有序的
如何保证可见性
synchronized在释放锁之前,会将线程工作内存的变量同步到主内存。解锁后,后续其他线程就可以访问最新的值
评论区