1

问题

我已经为 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 唤醒锁的真正问题?

4

1 回答 1

0

看来这确实是一个并发问题。我忽略了一个事实,即可以从单独线程中的非同步位置调用相关方法 - 在高度多线程的环境中这是一个明显的问题!

于 2012-01-21T19:40:53.233 回答