在两个线程下面的代码中,tr1 和 tr2 访问同一个 StringBuilder st。两者都调用同步方法 addRemove ,它所做的就是将一些内容附加到公共(public) StringBuilder 中,并在离开该方法之前删除该附加内容。 我使 addRemove() 方法同步,这意味着每个线程必须等待另一个线程完成。这意味着在离开该方法之前字符串生成器 st 的内容必须与“--”(在调用该方法之前)保持相同。但在实践中我们得到了这个
Thread# 0 created
Thread# 1 created
Thread# 0:--1
Thread# 1:--1
Thread# 0:--1
Thread# 1:--1
Thread# 0:--1
Thread# 1:--1
Thread# 0:--1
Thread# 0:--1
Thread# 1:--1
Thread# 0:--1
Thread# 1:--1
Thread# 0:--1
Thread# 1:--1
Thread# 0:--1
Thread# 1:--1
Thread# 1:--1
Thread# 1:--1
Thread# 0:--1
Thread# 1:--1
Thread# 0:--
这意味着即使在控件离开 addRemove() 之后,字符串“1”仍保留在 StringBuilder 中!这是为什么?毕竟,我使该方法同步了!
public class MyThread extends Thread{
public static int threadNum=0;
private int myNum=-1;
private StringBuilder st;
public MyThread(StringBuilder st){
this.st = st;
myNum = threadNum;
System.out.println("Thread# "+myNum+" created");
threadNum++;
}
public void run(){
for (int i = 0; i < 10; i++) {
addRemove();
}
}
/**
* Append and remove at the same time
*/
private synchronized void addRemove(){
st.append(myNum+"");
try {
Thread.sleep(Math.round(Math.random()*500));
} catch (InterruptedException e) {
System.err.println("Thread# "+myNum+" interupted");
}
st.deleteCharAt(st.length()-1);
System.out.println("Thread# "+myNum+":"+st);
}
public static void main(String[] args) {
StringBuilder st= new StringBuilder("--");
MyThread tr0= new MyThread(st);
MyThread tr1= new MyThread(st);
tr0.start();
tr1.start();
}
}
最佳答案
您正在以默认方式进行同步,这意味着该方法正在当前实例的对象 this
对象上进行同步,并且由于每个线程都是其自己的唯一对象,因此每个实例都会锁定自身。如果您希望同步工作,那么该方法应该由一个对象同步,也许是一个专门为此目的创建的静态对象。
public static final Object myLock = new Object;
synchronize(myLock) {
// ....
}
关于Java:为什么同步在这里不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24576400/