文章目录
前言
Synchronized是java中的关键字,是一种同步锁。它修饰的对象有以下几种:(类, 方法, 代码块),synchronized可以保证方法或代码块在运行时,同一时刻只有一个线程可以进入到临界区(互斥性)所以它也是排它锁,同时它还保证了共享变量的内存可见性。
在JDK1.6版本之前一直被称为''重量级锁'',但是在1.6之后进行了大量的优化. 主要包括为了减少获得锁和释放锁带来的性能消耗而引入的偏向锁和轻量级锁以及其它各种优化之后变得在某些情况下并不是那么重了。在线程冲突较少的情况下,可以获得和CAS类似的性能;而线程冲突严重的情况下,性能远高于CAS。
一、synchronized使用
1、synchronized同步代码块
//同步代码块会锁住o对象
synchronized(Object o){
}
2、synchronized修饰普通方法
//加在普通方法前锁的是this对象,即调用method方法的对象
public synchronized void method(){
}
3、 synchronized修饰静态方法
//加在静态方法前锁的是这个类对象
public static synchronized void method(){
}
二、synchronize下锁的状态
锁状态 | 是否是偏向锁 | 所标志 |
无锁不可偏向 | -- | 01 |
无锁可偏向 | 1 | 01 |
轻量级锁 | -- | 00 |
重量级锁 | -- | 10 |
注意事项:、
1、修改偏向锁的延迟时间: --xx:BiasedLockingStartupDelay=0
2、关闭指针压缩:--xx:UseComparessedOops
三、偏向锁
大部分情况下,锁不仅不存在竞争,而且总是由一个线程多次获得, 为了让获取锁的代价更低,就有了偏向锁。 当一个线程使用synchronized方式获取了一个锁对象时,会在该对象的对象头中存储当前线程的ID,后续这个线程再次去获取该锁对象时,直接进行线程ID的比较成功就表示该锁是偏向当前线程的,不需要再次获取锁了。
四、没有开启偏向锁情况下
1.无锁状态
一个对象没有被当做锁对象,处于无锁状态。
2.轻量级锁状态
一个对象被一个线程获取锁对象,处于轻量级锁状态。
3.重量级锁状态
一个对象已经持有了该锁对象,其他线程来争用,处于重量级锁状态。
代码演示:
package com.lyt.synchronize锁;
import org.openjdk.jol.info.ClassLayout;
public class Test01 {
public static void main(String[] args) throws InterruptedException {
A a=new A();
String str = ClassLayout.parseInstance(a).toPrintable();
System.out.println(str);//01 无锁状态
new Thread() {
@Override
public void run() {
synchronized(a) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
Thread.sleep(10);
str=ClassLayout.parseInstance(a).toPrintable();
System.out.println(str); //00 轻量级锁
new Thread() {
@Override
public void run() {
synchronized(a) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
Thread.sleep(10);
str=ClassLayout.parseInstance(a).toPrintable();
System.out.println(str); //00 轻量级锁
}
}
结果说明:
五、开启偏向锁情况下
1.无锁可偏向状态
一个对象没有被当做锁对象,处于无锁可偏向状态(对象头中没有记录线程ID)。
2.轻量级锁状态
一个对象被一个线程获取锁对象,处于轻量级锁状态(对象头中记录线程ID)。
一个对象被一个线程作为锁对象,释放锁对象之后(但是该线程没有消亡时),其他线程再获取锁对象,处于轻量级锁状态。
3.重量级锁状态
一个对象已经持有了该锁对象,还没有释放锁对象,其他线程也要获取该锁对象,处于重量级锁状态。
代码演示:
package com.lyt.synchronize锁;
import org.openjdk.jol.info.ClassLayout;
public class Test02 {
public static void main(String[] args) throws InterruptedException {
A a = new A();
String str = ClassLayout.parseInstance(a).toPrintable();
System.out.println(str);//101 无锁可偏向
new Thread() {
public void run() {
synchronized(a) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/*
* 显示的让当前线程不结束
* 如果结束了,下一个线程的id和刚才这个线程的id是一样的。
*/
try {
Thread.sleep(100000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
Thread.sleep(100);
str = ClassLayout.parseInstance(a).toPrintable();
System.out.println(str);//101 无锁可偏向
Thread.sleep(1000);//保证上一个线程已经把任务执行完毕了
new Thread() {
public void run() {
synchronized(a) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
Thread.sleep(100);
str = ClassLayout.parseInstance(a).toPrintable();
System.out.println(str);
}
}
结果说明: