Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/402.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 不同线程使用的同一变量在同步块内得到更新_Java_Object_Thread Safety - Fatal编程技术网

Java 不同线程使用的同一变量在同步块内得到更新

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

对于这个问题可能有一个简单的解决方案,但我不理解这里的概念

我正在尝试一个简单的程序,其中有3个线程执行一个同步块,以递增顺序打印字母。同步块对变量(StringBuffer对象)具有锁定。代码如下:

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