关于java:为什么StringBuilder访问似乎是同步的?

Why does StringBuilder access appear to be synchronized?

本问题已经有最佳答案,请猛点这里访问。

我想知道StringBuilder和StringBuffer类与实际使用之间的区别。因此,我编写了两个代码片段,其中我同时生成了3个线程,这些线程使用了StringBuilder和StringBuffer对象。

当我运行代码时,我希望所有3个线程在StringBuilder的情况下同时运行,在StringBuffer的情况下以同步方式运行。但在这两种情况下,它们都以同步方式运行。那么,StringBuffer类的用途是什么呢?困惑:

(对于字符串对象,所有3个线程同时运行)。我将分享代码片段供您参考。如果我理解多线程本身的概念是错误的,请纠正我。请同时更正代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// StringBuilder...

public class MultiTread implements Runnable{
private StringBuilder name;
public MultiTread(StringBuilder string){
name=string;
}

public void run(){
for(int i=0; i<=10; i++){
System.out.println(name.append(i));
}
}
public static void main(String[] args){
Thread th = new Thread(new MultiTread(new StringBuilder("thread1:")));
Thread th1 = new Thread(new MultiTread(new StringBuilder("thread2:")));
Thread th2 = new Thread(new MultiTread(new StringBuilder("thread3:")));

th.start();
th1.start();
th2.start();
}
}

..................

//StringBuffer...

public class MultiTreadBuf implements Runnable{
private StringBuffer name;
public MultiTreadBuf(StringBuffer string){
name=string;
}

public void run(){
for(int i=0; i<=10; i++){
System.out.println(name.append(i));
}
}
public static void main(String[] args){
Thread th = new Thread(new MultiTreadBuf(new StringBuffer("thread1:")));
Thread th1 = new Thread(new MultiTreadBuf(new StringBuffer("thread2:")));
Thread th2 = new Thread(new MultiTreadBuf(new StringBuffer("thread3:")));

th.start();
th1.start();
th2.start();
}
}

........

//String....

public class MuiltiTreadStr implements Runnable{
private String name;
public MuiltiTreadStr(String string){
name=string;
}

public void run(){
for(int i=0; i<=10; i++){
System.out.println(name+i);
}
}
public static void main(String[] args){
System.out.println("main begins...");
Thread th = new Thread(new MuiltiTreadStr("thread1:"));
Thread th1 = new Thread(new MuiltiTreadStr("thread2:"));
Thread th2 = new Thread(new MuiltiTreadStr("thread3:"));
System.out.println("spawning 3 threads...");
th.start();
th1.start();
th2.start();
System.out.println("main ends...");
}
}


每个线程使用不同的StringBuffers和StringBuilder实例。若要查看同步,必须在所有线程中使用相同的对象实例;-)


对预期行为和实际行为的描述是有帮助的,但是我猜想您看到了每个线程的顺序输出,但是期望看到的是来自不同线程的交错输出。

线程调度取决于系统。不能保证线程的调度是公平的(例如,具有相同优先级的线程将获得"时间片"),也不能保证线程将并发运行,即使在多处理器系统上也是如此。

另外,请记住,System.out.println()是同步的,对内部锁的争用不能保证得到公平或立即的解决。因此,有可能一个线程反复获得System.out上的锁,而其他线程直到该线程完成后才有机会打印。您可以使用java.util.concurrent.ReentrantLock获得"公平"锁定(可能会有性能损失)。

另一种可能是您的系统速度太快,以至于一个线程在下一个线程开始运行之前就完成了。更多的迭代将有助于检测这种情况。


您应该对所有线程使用相同的StringBuilder/StingBuffer实例。以便您可以看到同步。