在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
只是给定方法的本地(以及为什么同步在Buffer上)。这里是否真的需要同步,如果,为什么?
答案 0 :(得分:7)
这可能是性能优化。在oracle jvm中,重新获取已经锁定的锁定非常快。据推测,write
调用正在对StringBuffer进行大量调用。通过在呼叫write
之前锁定,锁定将通过所有这些呼叫保持,而不是为每次呼叫释放和重新获取。
答案 1 :(得分:6)
StringWriter
的空构造函数是
/**
* Create a new string writer using the default initial string-buffer
* size.
*/
public StringWriter() {
buf = new StringBuffer();
lock = buf;
}
没有任何共享,因此synchronized
块是不必要的。
除非...... write
委托给另一个主题,但我非常怀疑。
答案 2 :(得分:1)
getBuffer()
返回StringBuffer
,根据文档,StringBuffer
已经同步:
字符串缓冲区可供多个线程使用。这些方法在必要时进行同步,以便任何特定实例上的所有操作都表现得好像它们以某个顺序顺序发生,这与所涉及的每个单独线程的方法调用顺序一致。
这意味着在StringBuffer
上再次同步是完全矫枉过正的。对StringWriter
的更改将自动进行同步,因为它会在内部使用同步的StringBuffer
。
由于StringWriter
实例是方法调用的本地实例,因此不可能让多个线程同时访问同一个实例,这也使得不需要同步。
答案 3 :(得分:0)
这是一个错误。 每个线程在方法中创建自己的局部变量并在其上进行同步。每次进入方法线程时都会创建自己的对象监视器,而这些对象监视器不能被另一个线程保持,因为它是本地的并且仅存在于线程上堆栈!