8

在 JSON-java 库(org.json.JSONArray)中,我发现这个代码片段synchronized在方法局部变量周围有一个块

public String toString(int indentFactor) throws JSONException {
    StringWriter sw = new StringWriter();
    synchronized (sw.getBuffer()) {
        return this.write(sw, indentFactor, 0).toString();
    }
}

我不明白这里同步的必要性,因为StringWriter它只是给定方法的本地(以及为什么同步在缓冲区上)。这里是否真的需要同步,如果,为什么?

4

4 回答 4

8

这可能是性能优化。在 oracle jvm 中,重新获取已经持有的锁非常快。据推测,该write调用正在对 StringBuffer 进行多次调用。通过在调用之前锁定write,锁定将在所有这些调用中保持,而不是在每次调用时释放并重新获取。

于 2013-08-19T16:07:57.870 回答
6

的空构造函数StringWriter

/**
 * Create a new string writer using the default initial string-buffer
 * size.
 */
public StringWriter() {
    buf = new StringBuffer();
    lock = buf;
}

没有任何东西是共享的,因此该synchronized块是不必要的。

除非...write委托给另一个线程,但我对此表示严重怀疑。

于 2013-08-19T16:05:23.143 回答
1

getBuffer()返回 a StringBuffer,并且根据文档 aStringBuffer已经同步:

字符串缓冲区可以安全地被多个线程使用。这些方法在必要时同步,以便任何特定实例上的所有操作都表现得好像它们以某种串行顺序发生,该顺序与所涉及的每个单独线程进行的方法调用的顺序一致。

这意味着再次同步StringBuffer完全是矫枉过正。对 的更改StringWriter将自动同步,因为它在StringBuffer内部使用同步。

由于StringWriter实例是方法调用的本地实例,因此不可能有多个线程同时访问同一个实例,这也使得同步变得不必要。

于 2013-08-19T16:09:05.497 回答
0

这是一个错误。每个线程在方法中创建自己的局部变量并在其上进行同步。每次进入方法线程都会创建自己的对象监视器,该对象监视器不能被另一个线程持有,因为它是本地的并且只存在于线程的堆栈中!

于 2014-12-03T13:50:13.570 回答