synchronized锁重入
关键字synchronized拥有锁重入的功能,也就是在使用synchronized时,当一个线程得到一个对象的锁后,再次请求该对象是可以再次得到该对象的锁
示例:
public class SyncDubbo1 { public synchronized void method1(){ System.out.println("method1.."); method2(); } public synchronized void method2(){ System.out.println("method2.."); method3(); } public synchronized void method3(){ System.out.println("method3.."); } public static void main(String[] args) { final SyncDubbo1 sd = new SyncDubbo1(); Thread t1 = new Thread(new Runnable() { @Override public void run() { sd.method1(); } }); t1.start(); } } 结果: method1.. method2.. method3..
分析:线程调用method1时,也可以调到synchronized修饰的method2,method3方法,这是没有问题的,synchronized具有锁重入的功能
死锁
死锁问题,在设计程序时就应该避免双方相互持有对方的锁的情况
public class DeadLock implements Runnable{ private String tag; private static Object lock1 = new Object(); private static Object lock2 = new Object(); public void setTag(String tag){ this.tag = tag; } @Override public void run() { if(tag.equals("a")){ synchronized (lock1) { try { System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock1执行"); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock2) { System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock2执行"); } } } if(tag.equals("b")){ synchronized (lock2) { try { System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock2执行"); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock1) { System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock1执行"); } } } } public static void main(String[] args) { DeadLock d1 = new DeadLock(); d1.setTag("a"); DeadLock d2 = new DeadLock(); d2.setTag("b"); Thread t1 = new Thread(d1, "t1"); Thread t2 = new Thread(d2, "t2"); t1.start(); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } t2.start(); }
使用synchronized代码块加锁,比较灵活
public class ObjectLock { public void method1(){ synchronized (this) { //对象锁 try { System.out.println("do method1.."); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } public void method2(){ //类锁 synchronized (ObjectLock.class) { try { System.out.println("do method2.."); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } private Object lock = new Object(); public void method3(){ //任何对象锁 synchronized (lock) { try { System.out.println("do method3.."); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } }
synchronized代码块对字符串加锁,注意String常量池的缓存功能,需要使用字符串对象加锁,不要使用常量,因为常量在常量池只有一个引用,需要new一个对象进行加锁
public void method() { //new String("字符串常量") synchronized ("字符串常量") { try { while(true){ System.out.println("当前线程 : " + Thread.currentThread().getName() + "开始"); Thread.sleep(1000); System.out.println("当前线程 : " + Thread.currentThread().getName() + "结束"); } } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { final StringLock stringLock = new StringLock(); Thread t1 = new Thread(new Runnable() { @Override public void run() { stringLock.method(); } },"t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { stringLock.method(); } },"t2"); t1.start(); t2.start(); } 结果 当前线程 : t1开始 当前线程 : t1结束 当前线程 : t1开始 当前线程 : t1结束 当前线程 : t1开始。。。
锁对象的改变问题,声明了一个字符串变量,在加锁执行中,不要需要修改变量值,否则会失去这把锁
另外同一对象属性的修改不会影响锁的情况
public class ChangeLock { private String lock = "lock"; private void method(){ synchronized (lock) { try { System.out.println("当前线程 : " + Thread.currentThread().getName() + "开始"); lock = "change lock"; Thread.sleep(2000); System.out.println("当前线程 : " + Thread.currentThread().getName() + "结束"); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { final ChangeLock changeLock = new ChangeLock(); Thread t1 = new Thread(new Runnable() { @Override public void run() { changeLock.method(); } },"t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { changeLock.method(); } },"t2"); t1.start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } t2.start(); } } 结果 : t1 t2 基本同时执行,没有休眠2秒 当前线程 : t1开始 当前线程 : t2开始
相关推荐
`synchronized`的实现涉及到了很多底层细节,包括轻量级锁、偏向锁、自旋锁等优化策略,这些策略旨在提高锁的性能,减少不必要的上下文切换。例如,当锁竞争不激烈时,轻量级锁和偏向锁机制可以避免使用重量级的...
本文将从应用层、字节码层面和Java虚拟机规范层面三个方面深入探讨`synchronized`的工作原理和实现细节。 1. **应用层** - **临界区与临界资源**:临界区是指多线程环境下,包含共享资源的代码段。例如,一个简单...
本文主要探讨了Java中的`synchronized`关键字及其在JVM内部的实现机制。`synchronized`是Java中用于实现线程同步的关键字,它...理解这些细节有助于开发者更好地理解和使用`synchronized`,并优化多线程代码的性能。
尽管大部分开发者可能不需要直接处理这些细节,但对这些概念的基本理解可以帮助更好地设计和排查并发问题。实践是提高技能的关键,通过编写和调试多线程代码,可以进一步加深对这些概念的应用和理解。
4. **协议实现**:讲解同步CSMA协议的实现细节,可能涉及到硬件和软件层面的设计,以及如何在实际网络环境中部署。 5. **性能评估**:通过模拟实验和理论分析,比较同步CSMA与非同步CSMA的性能,包括吞吐量、延迟和...
"使用synchronized实现一个Lock代码详解" 在了解Lock和synchronized的区别...通过对Lock和synchronized的比较,我们可以看到,使用synchronized实现一个Lock需要注意很多细节,但是可以提供更好的可读性和可维护性。
内容包括单例模式的合理应用、静态变量的使用考量、对象创建与垃圾回收策略、final修饰符与内联优化、局部变量与实例变量的性能差异、包装类型与基本类型的内存影响、同步机制synchronized的谨慎使用、finalize方法...
18. **减少synchronized的使用**:过度使用synchronized可能导致性能瓶颈,尽量使用Lock接口提供的细粒度锁。 19. **避免大对象创建**:大对象可能导致新生代溢出,影响垃圾收集效率。 20. **合理使用volatile**:...
总的来说,Synchronized是Java中实现线程同步的重要工具,其背后的锁机制包括对象锁、类锁以及锁的状态转换等复杂细节,理解这些原理对于优化并发代码和排查多线程问题具有重要意义。因此,面试官,如果你对...
线程调度的细节由JVM决定,可能存在一定的非确定性。 同步代码块提供了更多的灵活性。它可以指定锁定的对象,这就像是用不同房子的钥匙打开同一个房子的屏风锁。这样,即使在持有锁的期间,线程也可以访问其他房子...
12. **同步与并发**:Java提供了synchronized关键字和并发工具类,用于管理多线程环境中的资源访问。 13. **构造器**:用于初始化对象,可以有默认构造器或带参数的构造器。 14. **final关键字**:用于声明常量、...
Java提供了丰富的并发工具类,如synchronized关键字、volatile变量、ThreadLocal、ConcurrentHashMap等。理解这些工具的使用和原理能帮助开发出高效且线程安全的代码。 5. 泛型: 泛型是Java 5引入的特性,用于提供...
通过以上内容的介绍,可以看出Synchronized关键字的使用及其背后的原理是相当丰富的,涉及了操作系统、JVM实现细节以及并发控制等多个方面。在面试中,对这些问题的理解程度往往能够反映一个开发者在并发编程领域的...
2. **封装**:封装是面向对象编程的基本原则之一,它隐藏了对象内部的实现细节,提供了公共接口来与外界交互。翁恺可能会解释如何通过访问修饰符(如public、private、protected)来实现封装。 3. **继承与多态**:...
Java提供了线程API,包括Thread类和Runnable接口,以及synchronized关键字和volatile变量来管理线程同步。理解这些概念,能帮助我们编写高效的多线程程序,充分利用计算资源。 集合框架是Java中不可或缺的一部分,...
7. **谨慎使用synchronized**:同步操作会带来性能开销,可能导致死锁。应尽量缩小同步代码范围,优先考虑使用同步方法而不是同步块,以减少锁的竞争。 8. **利用Buffer类**:如StringBuilder和StringBuffer用于...
5. **多线程同步**:Java提供了`synchronized`关键字实现线程同步,防止数据竞争。但是,过度使用会导致性能下降,应合理设计并发策略。 6. **异常处理**:Java的异常分为检查型异常和运行时异常。检查型异常需用`...
- 合理使用`synchronized`,避免过度同步,提高并发性能。 - 掌握并发工具类,如`CountDownLatch`、`CyclicBarrier`、`Semaphore`等,解决多线程协作问题。 7. **编译器优化与JVM参数调整**: - 了解JIT(Just-...
理解同步机制(如synchronized关键字,wait(),notify(),notifyAll()方法)是保证并发安全的关键。 7. **异常处理**:Java中的异常处理是通过try-catch-finally语句块实现的。理解和正确使用异常处理可以提高代码...
理解线程同步机制,如synchronized关键字、wait/notify、Lock接口,能避免竞态条件,保证程序的正确性。 六、IO流与NIO Java的IO流用于读写文件、网络通信等,分为字节流和字符流两大类。NIO(New IO)引入了缓冲...