synchronized
1.synchronized是我们解决线程不安全问题的一种手段,通过加锁的方式,实现了原子性,内存可见性,对于指令重排序,有一定的约束,但是不是完全禁止。
2.synchronized的使用
synchronized是加锁,放在不同的地方,锁的对象也不一样。
(1)修饰代码块 synchronized修饰代码块的时候,需要显示的写出来锁对象是谁(锁对象可以是任意对象)。
(2)修饰普通方法 修饰普通方法,锁对象是该实例,比如同一个实例,同时执行两个被synchronized修饰的方法时,只能有一个方法执行。
(3)修饰静态方法 修饰静态方法时,锁对象是类对象,静态方法,不属于任一个实例方法
3.synchronized的特性。
(1)互斥 某个线程执行到某个对象的synchronized中时,其他线程如果也执行到同一个对象synchronized就会阻塞等待。进入synchronized修饰的代码块就相当于加锁,退出就相当于解锁。
(2)刷新内存 即synchronized会在解锁前,一定保证把数据更新到了主内存里面。
(3)可重入 简单来说就是不会自己把自己锁死,在对象头里存有一部分内容,锁的持有者和计数器,如果一实例在执行被加锁的普通方法时,发现锁的持有者是他自己,那么就不再上锁,而是把计数器加1,这样就不会说因调用的方法里再调用加锁方法而导致的锁死问题。
4.synchronized是一个什么锁?
(这里的小结,只考虑了jdk8)
synchronized是一个乐观锁,也是一个悲观锁(主要看锁的竞争程度)。
synchronized不是读写锁,是普通的互斥锁。
synchronized是轻量级锁,也是重量级锁(随着锁的竞争程度的增加,会逐渐升级)。
synchronized开始是自旋锁,后面会逐渐升级。
synchronized是一个非公平锁,是一个可重入锁。
5.synchronized的锁机制/synchronized的锁升级,锁膨胀,锁消除,锁粗化
(1)锁升级/锁膨胀 无锁——>偏向锁——>自旋锁——>重量级锁,随着竞争程度的增加,synchronized的锁机制逐渐升级。(偏向锁并不是真正的锁,代表对某个线程有一定的偏向。大部分情况下,锁不仅不存在竞争,而且锁还经常由同一个对象获得。偏向锁就是一个标志,在对象头存储当前锁偏向的线程,当一个线程访问时,会先判断这个标志是否等于当前线程,如果等于当前线程,那就直接获得锁,如果为空,就把当前锁的对象头,设置成自己,如果不等于自己,锁就会升级)。
(2)锁消除 就是如果我们在一些不必要加锁的地方加了锁,那编译器或JVM会帮我们优化,将锁给消除掉。
(3)锁粗化 (粗细,指的是代码粒度的粗细,即加锁的代码的多或少)如果我们对一段代码频繁加锁,那么synchronized就会帮我们进行锁的粗化。
6.synchronized的原理
(1)synchronized的特性 原子性,内存可见性,有序性(指令重排序),非公平锁,可重入锁,不可中断(这里的不可中断不是指线程不能中断,而是指当拿不到锁的时候,这个阻塞的过程不可以中断)。
(2)synchronized的使用 修饰代码块,修饰普通方法,修饰静态方法。
(3)synchronized的锁机制 锁升级/锁膨胀,锁消除,锁粗化。
(4)synchronized的实现 主要跟monitor有关,监视器,每个对象都有一个monitor。