【问题标题】:What's the point of this synchronization?这种同步有什么意义?
【发布时间】:2009-12-30 21:40:05
【问题描述】:

这里同步的意义何在?

为什么不直接使用mConnectedThread.write(out)

代码 sn-p 来自 Android 的 BluetoothChat 示例(found here)

    /**
 * Write to the ConnectedThread in an unsynchronized manner
 * @param out The bytes to write
 * @see ConnectedThread#write(byte[])
 */
public void write(byte[] out) {
    // Create temporary object
    ConnectedThread r;
    // Synchronize a copy of the ConnectedThread
    synchronized (this) {
        if (mState != STATE_CONNECTED) return;
        r = mConnectedThread;
    }
    // Perform the write unsynchronized
    r.write(out);
}

【问题讨论】:

    标签: java android synchronization


    【解决方案1】:

    需要同步以确保您没有不一致的状态。

    如果没有同步,代码将是:

    public void write(byte[] out) {
        if (mState != STATE_CONNECTED) return;
        mConnectedThread.write(out);
    }
    

    现在,如果在 if 语句检查和方法调用之间关闭连接,mConnectedThread 可能会在方法调用执行之前被分配为 null。这将导致NullPointerException

    【讨论】:

    • 当然,在不知道更多信息的情况下,连接仍可能在同步块结束和实际 write() 调用之间关闭......现在可能会产生完全不同的错误。而且,如果 ConnectThread 在优雅地取消后处理 write(),那么只需将其分配给局部变量并检查 null 将是一种更简单的方法。
    【解决方案2】:

    当两个线程访问相同的数据(这里是变量mStatemConnectedThread)时,它们必须使用确保可见性的“内存屏障”。看来mStatemConnectedThread 的原子性在这里也很重要。

    可见性意味着一个线程所做的更改将对另一个线程可见。优化可能会导致缓存值,以便更改仅对生成它们的线程可见。同步会导致任何写入都反映在主内存中,并且任何读取都会绕过本地缓存并针对主内存进行。理论上,如果没有同步,一个线程可以设置mStatemConnectedThread,但其他线程可能永远不会“看到”这些更改,并永远等待该条件发生更改。

    原子性意味着不能单独观察多个动作。从另一个线程的角度来看,没有发生任何更改,或者所有更改都已发生。因此,例如,另一个线程永远不会看到 mStateSTATE_CONNECTED,而是在分配之前读取 mConnectedThread

    【讨论】:

      【解决方案3】:

      为了保持一致性,需要锁。 将 mConnectedThread 复制到单独的变量是因为写入(可能是长度操作)可以在锁之外完成。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-05-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-14
        • 2012-06-22
        • 2017-11-21
        相关资源
        最近更新 更多