这里的同步有什么意义?
为什么不使用mConnectedThread.write(out)
?
代码段来自Android (found here)
的BluetoothChat示例 /**
* 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);
}
答案 0 :(得分:2)
需要进行同步以确保您没有不一致的状态。
没有同步,代码将是:
public void write(byte[] out) {
if (mState != STATE_CONNECTED) return;
mConnectedThread.write(out);
}
现在,如果在语句调用执行之前,if语句检查和方法调用之间的连接可能会被分配为null mConnectedThread
。这将导致NullPointerException
。
答案 1 :(得分:1)
每当两个线程访问相同的数据(此处为变量mState
和mConnectedThread
)时,他们必须使用“内存屏障”来确保可见性。看来mState
和mConnectedThread
的原子性在这里也很重要。
可见性意味着一个线程所做的更改对另一个线程可见。优化可能会导致值被缓存,以便更改仅对创建它们的线程可见。同步导致任何写入都反映在主内存中,并且任何读取都会绕过本地缓存并对主内存进行。从理论上讲,如果没有同步,一个线程可以设置mState
和mConnectedThread
,但其他线程可能永远不会“看到”这些更改,并等待该条件发生变化。
原子性意味着无法单独观察多个动作。从另一个线程的角度来看,没有发生任何更改,或者发生了所有更改。因此,例如,另一个线程永远不会看到mState
是STATE_CONNECTED
,但在分配之前请先阅读mConnectedThread
。
答案 2 :(得分:1)
需要锁才能保持一致性。 将mConnectedThread复制到单独的变量是因为写入 - 这是一个可能的长度操作 - 可以在锁之外完成。