StringBuffer 同步是如何工作的?
How does StringBuffer synchronization work?
大家好!
我有点困惑 way/under StringBuffer 在什么情况下同步并阻止多线程访问。在下面的代码中,它打印出 for 循环 A 100 次然后 B 100 次等中的字母...注释掉同步 (sb){} 部分,它不再同步并且不起作用... .
那么 StringBuffer 是如何同步的...它会在什么限制下工作?有人可以简单地解释一下吗?一定要是原子操作吗?
谢谢!
约翰.
package threads.sync.ch13;
import java.util.ArrayList;
import java.util.List;
class Ex13_2 extends Thread {
static StringBuffer sb;
// StringBuilder sb;
String s;
public Ex13_2(StringBuffer sb) {
this.sb = sb;
}
public void run() {
synchronized (sb) {
// incr letter then print 100 X
sb.replace(0, sb.length(), this.s);
for (int i = 0; i < 100; i++) {
System.out.print(this.sb);
}
System.out.println();
}
}
public static void main(String[] args) {
// single Class Buffer per Instance...
sb = new StringBuffer("");
// Create Array of Multiple Thread Instances
// and start running them...
List<Ex13_2> e = new ArrayList<>();
for (char c = 'A'; c <= 'D'; c++) {
Ex13_2 t = new Ex13_2(sb);
t.s = c + "";
e.add(t);
}
for (Ex13_2 t : e) {
t.start();
}
}
}
首先,对于非共享使用,StringBuilder 更胜一筹(它是为此目的而编写的……它完全不同步,因此速度更快)。
回到StringBuffer。它的所有 public 方法都是同步的,所以它在内部是 "safe"。但以下不是原子的:
StringBuffer sb = //get_sb_from_somewhere;
sb.append("foo").append("bar);
为了使追加完全线程安全,将它们包裹在锁中,使用对象将使用的相同锁。通常这只是对象,就像这里的情况一样,所以:
synchronized (sb) {
sb.append("foo").append("bar);
}
我觉得你的 运行() 方法不错。
StringBuilder
中的每个方法都是线程安全的。但是您正在按顺序调用各种方法。所以每次调用一个方法都是互斥的,但不是整个系列的调用。
通过将整个系列放入一个 synchronized(sb) {}
块中,您可以使整个系列的调用互斥。
大家好!
我有点困惑 way/under StringBuffer 在什么情况下同步并阻止多线程访问。在下面的代码中,它打印出 for 循环 A 100 次然后 B 100 次等中的字母...注释掉同步 (sb){} 部分,它不再同步并且不起作用... .
那么 StringBuffer 是如何同步的...它会在什么限制下工作?有人可以简单地解释一下吗?一定要是原子操作吗?
谢谢!
约翰.
package threads.sync.ch13;
import java.util.ArrayList;
import java.util.List;
class Ex13_2 extends Thread {
static StringBuffer sb;
// StringBuilder sb;
String s;
public Ex13_2(StringBuffer sb) {
this.sb = sb;
}
public void run() {
synchronized (sb) {
// incr letter then print 100 X
sb.replace(0, sb.length(), this.s);
for (int i = 0; i < 100; i++) {
System.out.print(this.sb);
}
System.out.println();
}
}
public static void main(String[] args) {
// single Class Buffer per Instance...
sb = new StringBuffer("");
// Create Array of Multiple Thread Instances
// and start running them...
List<Ex13_2> e = new ArrayList<>();
for (char c = 'A'; c <= 'D'; c++) {
Ex13_2 t = new Ex13_2(sb);
t.s = c + "";
e.add(t);
}
for (Ex13_2 t : e) {
t.start();
}
}
}
首先,对于非共享使用,StringBuilder 更胜一筹(它是为此目的而编写的……它完全不同步,因此速度更快)。
回到StringBuffer。它的所有 public 方法都是同步的,所以它在内部是 "safe"。但以下不是原子的:
StringBuffer sb = //get_sb_from_somewhere;
sb.append("foo").append("bar);
为了使追加完全线程安全,将它们包裹在锁中,使用对象将使用的相同锁。通常这只是对象,就像这里的情况一样,所以:
synchronized (sb) {
sb.append("foo").append("bar);
}
我觉得你的 运行() 方法不错。
StringBuilder
中的每个方法都是线程安全的。但是您正在按顺序调用各种方法。所以每次调用一个方法都是互斥的,但不是整个系列的调用。
通过将整个系列放入一个 synchronized(sb) {}
块中,您可以使整个系列的调用互斥。