问题
我已经为 Android 开发了很长一段时间了。我开发的其中一个程序大量使用了WakeLocks。它通常是完美的(通常一次几天或几周,这是程序的要求),但我很少注意到这段代码中的特殊行为:
acquireWakeLock(wakeLockManager)
// Preconditions
assertFalse("Wake lock already acquired.", hasWakeLock());
assertNotNull("Wake lock manager not provided.", wakeLockManager);
// Acquire a wake lock.
wakeLock = wakeLockManager.newPartialWakeLock(DEBUG_TAG);
wakeLock.acquire();
// Postconditions
assertTrue("Wake Lock should be held!", hasWakeLock());
wherehasWakeLock()
简单地返回结果(wakeLock != null && wakeLock.isHeld())
并wakeLockManager.newPartialWakeLock(DEBUG_TAG)
封装了标准的“获取 PowerManager 然后返回唤醒锁”代码。出于测试的目的,断言语句是 JUnit 断言方法,所以我认为我们可以假设它们是正确的。
代码的问题是:最后的断言assertTrue(hasWakeLock())
- 似乎每隔几周就会失败一次,几乎没有解释。这意味着我在这里有三个可能的问题:(1)从未从 PowerManager 中检索到唤醒锁(2)我有一个并发问题,在极少数情况下,它在后置条件之前但在调用之后才生效acquire()
,或者(3)acquire()
有时是错误的。
问题调查
如上所述,我正在调查/已调查可能发生的三个潜在问题:
假设 1:未返回唤醒锁:
如果是这种情况,那么我会看到一个空指针异常。不可能这样。
假设 2:我有一个并发问题:
刚刚对所有涉及获取和释放的地方进行的形式验证证明wakeLock
强烈地让我相信情况并非如此。如果我的证明有问题,那么我可能会遇到并发问题,但它确实很隐蔽且很难找到。
假设 3: WakeLock.acquire() 是错误的,尽管文档说它有时可能无法获取锁:
我不喜欢这个假设,因为对于所有的 Android 用户,除了我自己之外,肯定有人已经注意到了这一点,而且几乎总是开发人员的代码,而不是库或操作系统代码有问题。再一次,奇怪的事情发生了,这可能是一个真正的 Android 错误,尽管很少出现。如果这个假设是真的,那么 acquire() 根本就没有获得唤醒锁,这将解释我所看到的行为。
那么 StackOverflow,是什么导致了这个问题?你觉得哪里不对?我是否遗漏了一些明显的东西,或者这可能是 Android 唤醒锁的真正问题?