Java同步机制三类典型场景技术问题咨询
Java同步机制三类场景问题解答
问题1:同步代码块与无同步方法的线程访问规则
- 当某线程执行
foo的synchronized(a)代码块时:
其他线程可以正常调用goo方法,也能直接操作对象a。因为goo没有任何同步约束,也没有尝试获取a对象的锁,所以不会被synchronized(a)的锁阻塞。但这种情况会引发线程安全问题,比如goo读取a.size()时,可能正好赶上foo在执行add操作的中间状态,导致读到的大小不准确。 - 反之,当线程通过无同步的
goo操作a时:
其他线程可以直接进入foo的synchronized(a)块。因为goo没有获取a的锁,所以a对象的锁处于未被持有的状态,其他线程能正常获取锁执行add操作。同样,这种场景下a的操作存在线程安全风险,读写没有互斥。
问题2:同步方法中wait与notifyAll的执行逻辑
当第一个线程执行到wait()时,会释放当前持有的this锁,进入等待状态;第二个线程此时能获取this锁进入foo方法,执行notifyAll()后,会唤醒所有等待this锁的线程(包括第一个线程)。
被唤醒的线程不会立刻继续执行,它会进入this锁的竞争队列,处于可运行状态但无法继续执行wait()之后的代码——直到当前持有this锁的第二个线程退出foo方法(不管是执行return还是走完整个方法),释放this锁后,被唤醒的线程才会参与锁的竞争,竞争成功后从wait()的位置继续执行后续操作。
问题3:通知lambda创建的线程b的几种方式
可以通过以下几种常见方式在goo方法中通知线程b:
- 共享volatile标志位:
在类A中定义一个volatile修饰的布尔变量,用于控制线程状态:class A implements Runnable { Thread b; private volatile boolean shouldStop = false; // volatile保证多线程可见性 void foo(){ b = new Thread(() -> { while(!shouldStop) { // 执行lambda逻辑 // 可添加短暂休眠避免空转 try { Thread.sleep(100); } catch(InterruptedException e) { break; } } }); b.start(); } void goo(){ shouldStop = true; // 通知线程停止 } } - Object锁配合wait/notify:
用一个共享对象作为锁,通过wait()/notify()实现线程间通信:class A implements Runnable { Thread b; private final Object lock = new Object(); private boolean isNotified = false; void foo(){ b = new Thread(() -> { synchronized(lock) { try { // 等待通知,用while避免虚假唤醒 while(!isNotified) { lock.wait(); } // 收到通知后执行后续逻辑 } catch(InterruptedException e) { Thread.currentThread().interrupt(); } } }); b.start(); } void goo(){ synchronized(lock) { isNotified = true; lock.notify(); // 唤醒等待的线程b // 或用notifyAll()唤醒所有等待该锁的线程 } } } - 线程中断机制:
调用线程的interrupt()方法设置中断标志,线程内部处理中断信号:class A implements Runnable { Thread b; void foo(){ b = new Thread(() -> { try { while(!Thread.currentThread().isInterrupted()) { // 执行lambda逻辑 Thread.sleep(100); // 若线程在阻塞状态,中断会抛出异常 } } catch(InterruptedException e) { // 捕获中断异常,结束线程 Thread.currentThread().interrupt(); // 保留中断标志 } }); b.start(); } void goo(){ b.interrupt(); // 发送中断信号通知线程 } }
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

