Параллельное программирование для новичка - PullRequest
0 голосов
/ 23 января 2019

Я пытаюсь понять параллельное программирование, и я не уверен в одном.У меня есть программа, которая имеет два потока, и они увеличивают одно и то же int (IntCell n).После 200 000 циклов int должен был составить 400 000, но это чуть больше 200 000. И теперь мне интересно, если один из потоков экспроприирован, когда второй увеличивает его, или они просто читают одно и то же значение одно за другим, затем увеличьте его и установите его как int два раза (две операции установки одного и того же int).Вот код:

class IntCell {
    private int n = 0;
    public int getN() {return n;}
    public void setN(int n) {this.n = n;}
}

class Count extends Thread {
    private static IntCell n = new IntCell();

    @Override
    public void run() {
        int temp;
        for (int i = 0; i < 200000; i++) {
            temp = n.getN();
            n.setN(temp + 1);
        }
    }

    public static void main(String[] args) {
        Count p = new Count();
        Count q = new Count();
        p.start();
        q.start();
        try { p.join(); q.join(); }
        catch (InterruptedException e) { }
        System.out.println("The value of n is " + n.getN());
    }
}

Ответы [ 2 ]

0 голосов
/ 23 января 2019

Вы не использовали синхронизацию , что вызывает две основные проблемы:

  1. Не гарантируется, что изменения общей переменной, сделанные одним потоком, будут видны другому
  2. Существует условие состязания между чтением текущего значения от n до temp и записью увеличенного значения - другой поток мог бы изменить значение между ними, и тогда это было бы перезаписано

Возможные решения включают использование synchronized -блоков, блокировок в пакете java.util.concurrent.locks или типов, которые поддерживают атомарные обновления, таких как AtomicInteger

0 голосов
/ 23 января 2019

Оба потока могут скопировать значение static IntCell n в локальное хранилище потока.

Используйте ключевое слово volatile, чтобы сигнализировать потокам о синхронизации локального значения потока и общего значения.

static volatile IntCell n

Другая проблема - сбой атомарности, критическая область:

// Thread 1    // Thread 2
temp = n.getN();
               temp = n.getN();
               n.setN(temp + 1);
n.setN(temp + 1);

С общим n это увеличит n не на 2, а всего на 1.

synchronize (n) {
    temp = n.getN();
    n.setN(temp + 1);
}

Это обеспечивает блокировку критической области на семафоре, связанном с n.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...