【问题标题】:java.lang.IllegalMonitorStateException: object not locked by thread before wait()java.lang.IllegalMonitorStateException:对象未在等待()之前被线程锁定
【发布时间】:2012-05-24 05:59:18
【问题描述】:

但是我在'名册'对象上同步它得到新的任何地方。怎么会?

违规代码:

 public Roster getRoster() {
    if (roster == null) {
        return null;
    }

    if (!roster.rosterInitialized) {
        try {
            synchronized (roster) {
                roster.reload();
                long waitTime = SmackConfiguration.getPacketReplyTimeout();
                long start = System.currentTimeMillis();
                while (!roster.rosterInitialized) {
                    if (waitTime <= 0) {
                        break;
                    }
                    roster.wait(waitTime);
                    long now = System.currentTimeMillis();
                    waitTime -= now - start;
                    start = now;
                }
            }
        }
        catch (InterruptedException ie) {
            // Ignore.
        }
    }
    return roster;
}

【问题讨论】:

  • 你在哪里打电话通知

标签: java android synchronize locks


【解决方案1】:

“gets new'ed”是指创建一个名册对象?

您确定同步正确吗?同步发生在实例上,而不是变量上。所以如果你这样做,例如

synchronized(roster) {
  roster = new Roster();
  // do something
}

那么你只同步到old,而不是newroster

所以下面的代码应该会产生同样的错误:

Roster roster = new Roster();
Roster othervariable = roster;
synchronized(othervariable) {
  roster = new Roster(); // create a new roster
  othervariable.wait(1000); // OK, since synchronized with this instance!
  roster.wait(1000); // NOT OK, not synchronized with *new* roster!
}

同步不会发生在变量的名称上,而是发生在内容上。如果覆盖内容,则不会重新同步到新值!

【讨论】:

  • 虽然你在这个观察中是对的,但我看不出它是如何导致异常的。能详细点吗?
  • 选项 #1 是如果 roster.reload() 可以以某种方式更改 roster 变量引用的对象。选项 #2 是,在您进行 wait() 调用之前或当您在其中时,其他一些线程会更改 roster 变量所指的内容。在任何一种情况下,您同步的花名册都不会是您正在等待()的花名册。
猜你喜欢
  • 1970-01-01
  • 2014-12-22
  • 1970-01-01
  • 2018-11-30
  • 2017-03-17
  • 2018-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多