5 ms·
Can someone with a better understanding of the Java memory model comment on this, referring to StringBuffer: "Say you had the code // run in two threads s
by spacemanaki 14y ago
Can someone with a better understanding of the Java memory model comment on this, referring to StringBuffer:
"Say you had the code
// run in two threads
sb.append(key).append("=").append(value).append(", ");
Each append is thread safe, but the lock could be release at any point meaning you could get [1]
key1=value1, key2=value2,
key1=key2value1=, value2,
key1key2==value1value2, ,
What makes it worse is that the JIT and JVM will attempt to hold onto the lock between calls in the interests of efficiency.[2]"
[1] is weirdly worded, or even wrong (I don't think "the lock could be release at any point" is correct) but the sample result does make sense to me if there are multiple threads banging on it at once. StringBuffer's append methods are synchronized, but without external synchronization, multiple calls could be interleaved.
I don't recall ever having heard of [2] before, and my copy of Java Concurrency in Practice isn't immediately at hand.
- AYBABTME 14y agoI don't know if that's the answer you're looking for, but a call to append is synchronized: public synchronized StringBuffer append(/* Something */); ... but chaining them doesn't mean that the chain is synchronized. sb.append(key).append("=").append(value).append(", "); is executed the same way as sb.append(key); sb.append("="); sb.append(value); sb.append(", "); Two concurrent threads running this part of code might do this: sb.append(key); // # 1 sb.append("="); // # 2 sb.append(value); // # 3 sb.append(", "); // # 4 // Thread 1 executes #1 // Thread 2 executes #1 // Thread 1 executes #2 // Thread 1 executes #3 // Thread 2 executes #2 // Thread 2 executes #3 // Thread 2 executes #4 // Thread 1 executes #4 This can be executed in many more different ways. To ensure that only one thread executes those `append` at once, you would have to synchronize on the `StringBuffer` instance: synchronize(sb){ sb.append(key).append("=").append(value).append(", "); } Then only one thread will do the appending at a time. But this introduce yet another lock in your code, and render the `synchronized` methods useless and redondant.
- Cloven 14y agoit introduces a lock in your code, because that is what you want -- you want the string to be built by one thread only. Why the strange comments about 'yet another lock' and the synchronized methods being 'useless' or 'redondant' (sic)?
- spacemanaki 14y agoThanks, I looked up the source and saw that append was synchronized too. I was mostly asking about this claim from the OP: "the JIT and JVM will attempt to hold onto the lock between calls in the interests of efficiency". I don't think that's true.