解释一下 Synchronized 中 偏向锁 轻量级锁 重量级锁的 含义,并且用例子解释一下
时间: 2023-11-14 13:14:13 浏览: 83
Synchronized 是 Java 中用于实现线程同步的关键字,它可以保证在同一时刻只有一个线程可以访问被 Synchronized 修饰的代码块或方法。在实现线程同步时,Synchronized 使用了不同的锁,包括偏向锁、轻量级锁和重量级锁。
偏向锁是一种针对单线程场景的优化锁,它会在第一次获取锁时,将当前线程 ID 记录在锁的对象头中,之后该线程再次获取锁时,无需竞争锁资源,直接获取锁即可。举个例子:
```java
public class BiasLockExample {
private static Object lock = new Object();
public static void main(String[] args) {
long start = System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
synchronized (lock) {
// do something
}
}
System.out.println("Time cost: " + (System.currentTimeMillis() - start) + "ms");
}
}
```
在以上代码中,由于所有的锁都是在同一个线程中获取的,因此会使用偏向锁进行优化,从而提高了程序的执行效率。
轻量级锁是一种适用于竞争不激烈的场景的锁,它会在第一次获取锁时,将对象头中的信息复制到线程栈中,然后通过 CAS 操作来更新对象头中的信息,如果更新成功,则表示该线程获取了锁,如果失败,则需要升级为重量级锁。举个例子:
```java
public class LightweightLockExample {
private static Object lock = new Object();
public static void main(String[] args) {
new Thread(() -> {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + " got the lock");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(() -> {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + " got the lock");
}
}).start();
}
}
```
在以上代码中,由于第一个线程获取锁后会休眠 5 秒钟,因此第二个线程需要等待第一个线程释放锁之后才能获取锁,而这时就会使用轻量级锁进行优化。
重量级锁是一种适用于竞争激烈的场景的锁,它会导致线程阻塞,从而消耗大量的系统资源。举个例子:
```java
public class HeavyweightLockExample {
private static Object lock = new Object();
public static void main(String[] args) {
new Thread(() -> {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + " got the lock");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(() -> {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + " got the lock");
}
}).start();
}
}
```
在以上代码中,由于两个线程同时竞争同一个锁,因此会使用重量级锁进行优化,从而导致第二个线程需要等待第一个线程释放锁之后才能获取锁,这样会导致线程阻塞,从而影响程序的执行效率。
阅读全文