从jvm源码看synchronized

synchronized的使用

修饰实例方法

修饰静态方法

修饰代码块

总结

Synchronzied的底层原理

对象头和内置锁(ObjectMonitor)

synchronzied的底层原理

synchronized的优化

偏向锁

轻量级锁

轻量级锁膨胀

重量级锁

自旋

编译期间锁优化

总结

参考资料

synchronized的使用

synchronized关键字是Java中解决并发问题的一种常用方法,也是最简单的一种方法,其作用有三个:(1)互斥性:确保线程互斥的访问同步代码(2)可见性:保证共享变量的修改能够及时可见(3)有序性:有效解决重排序问题,其用法也有三个:

修饰实例方法

修饰静态方法

修饰代码块

修饰实例方法 public class Thread1 implements Runnable{ //共享资源(临界资源) static int i=0; //如果没有synchronized关键字,输出小于20000 public synchronized void increase(){ i++; } public void run() { for(int j=0;j<10000;j++){ increase(); } } public static void main(String[] args) throws InterruptedException { Thread1 t=new Thread1(); Thread t1=new Thread(t); Thread t2=new Thread(t); t1.start(); t2.start(); t1.join();//主线程等待t1执行完毕 t2.join();//主线程等待t2执行完毕 System.out.println(i); } /** * 输出结果: * 20000 */ } 修饰静态方法 public class Thread1 { //共享资源(临界资源) static int i = 0; //如果没有synchronized关键字,输出小于20000 public static synchronized void increase() { i++; } public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(new Runnable() { public void run() { for (int j = 0; j < 10000; j++) { increase(); } } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { for (int j = 0; j < 10000; j++) { increase(); } } }); t1.start(); t2.start(); t1.join();//主线程等待t1执行完毕 t2.join();//主线程等待t2执行完毕 System.out.println(i); } /** * 输出结果: * 20000 */ } 修饰代码块 public class Thread1 implements Runnable{ //共享资源(临界资源) static int i=0; @Override public void run() { for(int j=0;j<10000;j++){ //获得了String的类锁 synchronized (String.class){ i++;} } } public static void main(String[] args) throws InterruptedException { Thread1 t=new Thread1(); Thread t1=new Thread(t); Thread t2=new Thread(t); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(i); } /** * 输出结果: * 20000 */ } 总结

synchronized修饰的实例方法,多线程并发访问时,只能有一个线程进入,获得对象内置锁,其他线程阻塞等待,但在此期间线程仍然可以访问其他方法。

synchronized修饰的静态方法,多线程并发访问时,只能有一个线程进入,获得类锁,其他线程阻塞等待,但在此期间线程仍然可以访问其他方法。

synchronized修饰的代码块,多线程并发访问时,只能有一个线程进入,根据括号中的对象或者是类,获得相应的对象内置锁或者是类锁

每个类都有一个类锁,类的每个对象也有一个内置锁,它们是互不干扰的,也就是说一个线程可以同时获得类锁和该类实例化对象的内置锁,当线程访问非synchronzied修饰的方法时,并不需要获得锁,因此不会产生阻塞。

Synchronzied的底层原理 对象头和内置锁(ObjectMonitor)

根据jvm的分区,对象分配在堆内存中,可以用下图表示:

从jvm源码看synchronized

对象头

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/8d7a38a13765e75260ff93bfe13448b6.html