Java 不同线程使用的同一变量在同步块内得到更新
对于这个问题可能有一个简单的解决方案,但我不理解这里的概念 我正在尝试一个简单的程序,其中有3个线程执行一个同步块,以递增顺序打印字母。同步块对变量(StringBuffer对象)具有锁定。代码如下:Java 不同线程使用的同一变量在同步块内得到更新,java,object,thread-safety,Java,Object,Thread Safety,对于这个问题可能有一个简单的解决方案,但我不理解这里的概念 我正在尝试一个简单的程序,其中有3个线程执行一个同步块,以递增顺序打印字母。同步块对变量(StringBuffer对象)具有锁定。代码如下: public class SimpleThread extends Thread implements Runnable{ private StringBuffer myBuffer; public StringBuffer getMyBuffer() { re
public class SimpleThread extends Thread implements Runnable{
private StringBuffer myBuffer;
public StringBuffer getMyBuffer() {
return myBuffer;
}
public void setMyBuffer(StringBuffer myBuffer) {
this.myBuffer = myBuffer;
}
public SimpleThread(StringBuffer myBuffer) {
this.myBuffer = myBuffer;
}
public void run() {
synchronized (this.myBuffer) {
while((int)(this.myBuffer.charAt(0))!=68) {
for(int i=0;i<3;i++) {
System.out.println(this.myBuffer.charAt(0));
}
char x = this.myBuffer.charAt(0);
this.myBuffer.setCharAt(0, (char) (x+1));
}
//this.myBuffer.setCharAt(0, 'A');
}
}
public static void main(String[] args) {
StringBuffer safeBuffer = new StringBuffer();
safeBuffer.append('A');
SimpleThread one = new SimpleThread(safeBuffer);
one.setName("One");
one.start();
SimpleThread two = new SimpleThread(safeBuffer);
two.setName("Two");
two.start();
SimpleThread three = new SimpleThread(safeBuffer);
three.setName("Three");
three.start();
}
它只在线程一执行时打印值,而对于其他两个线程,变量myBuffer的值变为D。我不明白的是,为什么更改一个对象的变量会反映其他对象?
synchronized
意味着一次只能有一个线程执行代码块。您可能会混淆措辞,以为它同步了变量
当您编写synchronized(this.myBuffer)
时,您告诉程序在决定线程是否可以执行以下代码块时使用myBuffer作为锁
这意味着当线程尝试执行synchronized(This.myBuffer){}
时,它将尝试获得myBuffer上的锁
- 如果没有其他线程拥有锁,它将获得锁并执行 代码块李>
- 如果另一个线程拥有锁,它将等待另一个线程释放锁(通常通过在代码块内完成代码运行)
synchronized(this.myBuffer){}
的内容
由于线程“一”首先启动,它将首先获得锁并完成所有工作,从而将myBuffer内容增加到D,然后再将其交给线程“二”。不清楚您希望发生什么,以及为什么。只有一个共享缓冲区。它还能怎么执行呢?谢谢你的解释。但是,this.myBuffer意味着执行它的对象的myBuffer的值。我们已经初始化了三个不同的对象,因此它们应该有自己的myBuffer副本。现在,当轮到“2”时,此时myBuffer的值应该是“A”,因为它的副本的值还没有更新。我能解释一下吗?java中的所有内容都是按值传递的,但是当我们传递对象的值时,值就是对对象的引用。您正在将同一对象的引用传递给所有3个线程。在此了解更多信息:您可能会看到,当您将某个内容传递给某个方法时,该方法会生成一个副本。是的,但当它是一个对象时,它会复制引用。如果您传递一个基本元素,例如int,那么该值就是数字本身。第一个大写字母的任何类型都是Object的子类。即使是字符串,它们也是不可变的,就像原语一样。是的,但当它是一个对象时,它会复制引用——这一点很清楚。谢谢你的解释。
A
A
A
B
B
B
C
C
C