深入理解 synchronized:到底锁的是谁?
在 Java 多线程并发编程里synchronized是保证线程安全的核心关键字但很多开发者只知道它能加锁却不清楚它到底锁的是什么、不同写法锁的范围有何区别。这篇文章就把 synchronized 的锁对象、作用范围、经典测试用例一次性讲透代码与测试结果完全还原帮你彻底搞懂 synchronized 的 “锁事”。一、synchronized 锁的核心结论synchronized 本质锁的是对象而非代码不同写法对应不同锁对象修饰实例方法→ 锁当前实例对象this修饰静态方法→ 锁当前类的 Class 对象修饰代码块→ 锁括号内指定的对象只有锁的是同一个对象多线程才会互斥等待锁不同对象互不影响。二、完整测试用例一模一样还原测试用例 1synchronized 修饰实例方法锁 this代码public class SyncInstanceMethod { // 同步实例方法锁当前对象 this public synchronized void test() { System.out.println(Thread.currentThread().getName() 进入同步方法); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() 退出同步方法); } public static void main(String[] args) { // 同一个对象 SyncInstanceMethod instance new SyncInstanceMethod(); new Thread(() - instance.test(), 线程A).start(); new Thread(() - instance.test(), 线程B).start(); } }执行结果线程A 进入同步方法 线程A 退出同步方法 线程B 进入同步方法 线程B 退出同步方法结论同一个实例对象的同步方法多线程互斥执行锁是当前实例 this。测试用例 2不同实例调用实例同步方法互不锁代码public class SyncInstanceMethodDiff { public synchronized void test() { System.out.println(Thread.currentThread().getName() 进入同步方法); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() 退出同步方法); } public static void main(String[] args) { // 两个不同实例 SyncInstanceMethodDiff instance1 new SyncInstanceMethodDiff(); SyncInstanceMethodDiff instance2 new SyncInstanceMethodDiff(); new Thread(() - instance1.test(), 线程A).start(); new Thread(() - instance2.test(), 线程B).start(); } }执行结果线程A 进入同步方法 线程B 进入同步方法 线程A 退出同步方法 线程B 退出同步方法结论不同实例的同步方法锁对象不同不互斥并发执行。测试用例 3synchronized 修饰静态方法锁 Class 对象代码public class SyncStaticMethod { // 同步静态方法锁当前类 Class 对象 public static synchronized void test() { System.out.println(Thread.currentThread().getName() 进入静态同步方法); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() 退出静态同步方法); } public static void main(String[] args) { new Thread(() - SyncStaticMethod.test(), 线程A).start(); new Thread(() - SyncStaticMethod.test(), 线程B).start(); } }执行结果线程A 进入静态同步方法 线程A 退出静态同步方法 线程B 进入静态同步方法 线程B 退出静态同步方法结论静态同步方法锁的是类的 Class 对象全局唯一所有线程互斥。测试用例 4synchronized 修饰代码块指定锁对象代码public class SyncBlock { // 自定义锁对象 private final Object lock new Object(); public void test() { // 同步代码块锁 lock 对象 synchronized (lock) { System.out.println(Thread.currentThread().getName() 进入同步代码块); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() 退出同步代码块); } } public static void main(String[] args) { SyncBlock instance new SyncBlock(); new Thread(() - instance.test(), 线程A).start(); new Thread(() - instance.test(), 线程B).start(); } }执行结果线程A 进入同步代码块 线程A 退出同步代码块 线程B 进入同步代码块 线程B 退出同步代码块结论同步代码块锁指定对象粒度更灵活是企业开发推荐写法。测试用例 5实例锁 VS 类锁互不干扰代码public class SyncInstanceAndClass { // 实例方法锁this public synchronized void instanceMethod() { System.out.println(Thread.currentThread().getName() 进入实例方法); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() 退出实例方法); } // 静态方法锁Class public static synchronized void staticMethod() { System.out.println(Thread.currentThread().getName() 进入静态方法); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() 退出静态方法); } public static void main(String[] args) { SyncInstanceAndClass instance new SyncInstanceAndClass(); new Thread(() - instance.instanceMethod(), 线程A).start(); new Thread(() - SyncInstanceAndClass.staticMethod(), 线程B).start(); } }执行结果线程A 进入实例方法 线程B 进入静态方法 线程A 退出实例方法 线程B 退出静态方法结论实例锁this和类锁Class是两把完全独立的锁互不阻塞。三、一张表总结 synchronized 锁对象写法锁对象作用范围实例方法 synchronized当前实例 this同一实例互斥静态方法 synchronized当前类 Class全局所有实例互斥同步代码块 synchronized (obj)指定对象 obj仅锁 obj 范围四、核心要点回顾synchronized 永远锁对象不锁代码。只有锁同一个对象才会互斥。实例锁和类锁是两把独立锁互不影响。代码块锁粒度最细性能最优优先使用。搞懂 synchronized 到底锁谁是写出高并发、线程安全代码的第一步
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2438454.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!