одна и та же переменная, используемая разными потоками, обновляется внутри синхронизированного блока - PullRequest
0 голосов
/ 06 февраля 2020

Возможно, эта проблема проста, но я не понимаю концепции здесь.

Я пытаюсь выполнить простую программу, в которой у меня есть 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();
    }

Вывод для программы:

A
A
A
B
B
B
C
C
C

Он печатает значение только при выполнении потока One, а для двух других потоков - переменной myBuffer. становится D. Чего я не понимаю, так почему изменение переменной для одного объекта отражается для других объектов?

1 Ответ

1 голос
/ 06 февраля 2020

synchronized означает, что только один поток может одновременно выполнять блок кода. Возможно, вы путаете формулировку, считая, что она синхронизирует переменную.

Когда вы пишете synchronized (this.myBuffer), вы говорите программе использовать myBuffer в качестве блокировки при принятии решения, может ли поток выполнить следующий блок кода.

Это означает, что когда поток пытается выполнить synchronized (this.myBuffer) { }, он попытается получить блокировку myBuffer.

  • Если ни один другой поток не имеет блокировки, он получит ее и выполнит блок кода.
  • Если другой поток имеет блокировку, он будет ждать, пока другой поток не снимет блокировку (обычно путем завершения выполнения кода внутри блока кода).

Это означает, что все потоки будут всегда по очереди выполняя содержимое synchronized (this.myBuffer) { }.

Так как поток «Один» запускается первым, он сначала получает блокировку и завершает sh всю работу, которую он имеет, таким образом, увеличивая содержимое myBuffer до D, прежде чем Передача в нить "Два".

...