synchronized特性:
- 原子性:所谓原子性就是指一个操作或者多个操作,要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行
- 可见性:可见性是指多个线程访问一个资源时,该资源的状态、值信息等对于其他线程都是可见的。
- 有序性:有序性值程序执行的顺序按照代码先后执行。
synchronized和volatile都具有有序性,Java允许编译器和处理器对指令进行重排,但是指令重排并不会影响单线程的顺序,它影响的是多线程并发执行的顺序性。synchronized保证了每个时刻都只有一个线程访问同步代码块,也就确定了线程执行同步代码块是分先后顺序的,保证了有序性。
这里的有序性指的是会发生指令重排情况但最终结果会一致
- 可重入性: synchronized和ReentrantLock都是可重入锁。当一个线程试图操作一个由其他线程持有的对象锁的临界资源时,将会处于阻塞状态,但当一个线程再次请求自己持有对象锁的临界资源时,这种情况属于重入锁。通俗一点讲就是说一个线程拥有了锁仍然还可以重复申请锁。
synchronized锁底层实现
对象再内存中的存储模型:
把对象当成一把锁实际上就是在这个对象的markword记录了锁信息
锁的四种状态:无锁状态、偏向锁、自旋锁、重量级锁
- 无锁:对象一开始就是无锁状态。
- 偏向锁: 相当于给对象贴了一个标签 (将自己的线程 id 存入对象头中),下次我再 进来时,发现标签是我的,我就可以继续使用了。
- 自旋锁: 想象一下有一个厕所,里面有一个人在,你很想上但是只有一个坑位,所以你只能徘徊等待,等那个人出来以后,你就可以使用了 。 这个自旋是使用 cas 来保证原子性的,关于 cas 我这里就不再赘述了。
- 重量级锁: 直接向 cpu 去申请申请锁 ,其他的线程都进入队列中等待。
- 偏向锁:一个线程获取锁时会由无锁升级为偏向锁
- 自旋锁:当产生线程竞争时由偏向锁升级为自旋锁,想象一下 while(true) ;
- 重量级锁:当线程竞争到达一定数量或超过一定时间时,晋升为重量级锁