Android Things GPIO中断直至wait()超时才触发问题求助
GPIO中断需等待wait()超时才触发的解决方案
看起来你遇到的是经典的线程等待/通知机制的时序问题,结合你的代码,我来分析问题根源并给出具体修复方案:
问题根源分析
你的代码逻辑框架没问题,但有两个关键隐患会导致你看到的现象:
- 中断触发早于wait()调用:如果GPIO中断在
waitForInterrupt()调用之前就发生了,notifyAll()会被执行,但此时还没有线程在等待notifier对象,后续的wait(5000)会一直等到超时才结束。 - 锁竞争导致回调阻塞:如果有其他线程长期持有
notifier的锁,GPIO回调线程会被卡在synchronized(notifier)块外,直到wait()超时释放锁后,回调才能执行,看起来就像中断延迟触发了。
修复方案
方案1:添加中断触发标志位(解决时序问题)
通过一个volatile修饰的标志位记录中断是否已发生,避免错过提前触发的中断:
public class Foo { private static final Object notifier = new Object(); // volatile保证多线程间的可见性,确保回调线程修改后,等待线程能立刻看到 private static volatile boolean interruptTriggered = false; public static GpioCallback interrupt = pin -> { synchronized (notifier) { interruptTriggered = true; notifier.notifyAll(); Log.d("FOO", "Interrupt triggered, notified waiting threads"); } return true; }; public void waitForInterrupt() { try { synchronized (notifier) { // 先检查是否已经触发过中断,避免等待超时 if (!interruptTriggered) { Log.d("FOO", "Waiting for interrupt..."); notifier.wait(5000); } // 重置标志位,方便下次调用 interruptTriggered = false; } Log.d("FOO", "Done."); } catch (InterruptedException e) { // 不要吞掉中断状态,恢复线程的中断标记 Thread.currentThread().interrupt(); Log.e("FOO", "Wait operation was interrupted", e); } } }
方案2:排查锁竞争问题(解决回调阻塞)
如果添加标志位后问题依然存在,需要检查是否有其他线程占用notifier锁。可以在synchronized块内添加日志,追踪锁的获取顺序:
- 在回调的
synchronized块内添加日志,确认回调线程何时获取到锁 - 在
waitForInterrupt的synchronized块内添加日志,确认等待线程何时获取到锁
通过日志就能清楚看到是否有锁阻塞的情况,进而定位占用锁的线程。
额外注意事项
- 确认GPIO回调已正确注册到目标引脚,并且边沿触发模式(上升沿/下降沿/双边沿)配置符合你的需求
- 不要在
synchronized块内执行耗时操作,避免阻塞其他需要获取锁的线程
内容的提问来源于stack exchange,提问作者David Schneider
相关产品推荐
相关产品推荐

