Java中的synchronized 优化方法之锁膨胀机制
Java中的synchronized是一种线程安全的同步机制,能够保证多个线程访问同一个对象的方法或段代码时,只有一个线程执行,其他线程等待,直到执行完毕后才能继续执行。然而,synchronized也可能带来一些性能问题。因此,Java提出了一些优化方法,其中之一就是锁膨胀机制。
什么是锁膨胀机制?
当一个线程访问一个对象的同步方法时,Java虚拟机会给该线程分配一个轻量级锁(也称为偏向锁),随着竞争的增加,会升级为重量级锁(也称为互斥锁),锁的等级越高,进入和退出同步块时所需的开销就会越大,从而影响代码的性能。
为了避免轻量级锁的使用过于频繁,Java提出了锁膨胀机制。如果一个线程多次获得轻量级锁失败,Java虚拟机会将该锁升级为重量级锁。当然,反之也会发生,如果一个线程持有重量级锁,但在synchronized代码块完成前就退出了,Java虚拟机会将该锁降级为轻量级锁。这种锁升级或降级的过程就被称为锁膨胀机制。
示例说明
为了说明锁膨胀机制,我们可以考虑以下两个示例:
- 没有锁膨胀机制
public class MyThread extends Thread {
private Integer i = 0;
public synchronized void increment() {
i++;
}
public void run() {
for (int j = 0; j < 10000000; j++) {
increment();
}
}
public static void main(String[] args) throws InterruptedException {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(t1.i + t2.i);
}
}
在这个示例中,我们定义了一个MyThread类,其中有一个increment方法,用来自增i这个变量。同时,我们在increment方法前加上了synchronized关键字,保证了多个线程对i变量的访问不会冲突。然后我们创建了两个线程t1和t2,让它们分别调用increment方法进行递增,最后输出递增的结果。
这里我们发现,如果没有锁膨胀机制,两个线程间会频繁地切换轻量级锁和重量级锁,导致性能下降。如果我们运行上述代码,就会发现线程执行需要较长时间。
- 使用锁膨胀机制
public class MyThread extends Thread {
private Integer i = 0;
public void increment() {
synchronized (this) {
i++;
}
}
public void run() {
for (int j = 0; j < 10000000; j++) {
increment();
}
}
public static void main(String[] args) throws InterruptedException {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(t1.i + t2.i);
}
}
在这个示例中,我们对上一个示例进行改进,将synchronized从方法中移到了代码块中,并将锁的对象改为this。这样就可以避免轻量级锁和重量级锁之间的频繁转换,从而提高了性能。
如果我们运行上述代码,就会发现线程执行时间有了明显的缩短。
小结
Java中的synchronized是一种重要的线程同步机制,但如果使用不当,会带来性能问题。为了优化synchronized的性能,Java提出了锁膨胀机制,避免了轻量级锁和重量级锁之间频繁切换的情况。我们需要根据实际情况合理地使用synchronized和锁膨胀机制,从而提高代码的性能。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java中的synchronized 优化方法之锁膨胀机制 - Python技术站