Что такое локальные переменные в потоке?

Согласно Java Concurrency in Practices,

Каждый поток имеет свой собственный программный счетчик, стек и локальные переменные.

У меня есть путаница с утверждением "локальные переменные". Что здесь означают локальные переменные? Означает ли это локальную копию общей переменной в потоке, например, если два потока асинхронно читают одну глобальную переменную, каждый поток содержит копию этой переменной в своем выполнении кода/пути?

Или это относится к переменным, которые объявлены и созданы явно внутри потоков и которые не используются совместно?


person Farruh Habibullaev    schedule 15.01.2020    source источник


Ответы (2)


Локальные переменные — это просто переменные локальной области видимости. См. JLS 6.3. больше информации и примеров.

В следующем методе

void method(String param1, int param2) {
    String concat = param1 + param2;
    if(concat.length() > 2) {
        int length = concat.length();
        System.out.println("concat is " + length + " character long");
    }
}

К локальным переменным относятся аргументы метода (param1, param2), переменные, объявленные в методе (concat, length)

На ваш вопрос это переменные, жизнь которых не выходит за рамки выполнения метода.

person ernest_k    schedule 15.01.2020
comment
Спасибо за объяснение. Теперь это действительно имеет смысл. - person Farruh Habibullaev; 15.01.2020

Учитывайте, когда запускаются потоки, например:

public class MyThread implements Runnable {

    private String name;

    public void kickOff() {

        Thread thread1 = new Thread();
        thread1.start();
        Thread thread2 = new Thread();
        thread2.start();
    }

    public void run() {
        Person person = findSomeRandomPerson();
        printPerson(person);
    }

    public void printPerson(Person person) {
        String desc = person.toString();
        doSomething(desc);

        // This is bad - the threads can interfere
        this.name = "Hello " + desc;
        doMore(this.name)            
    }
}

Итак, здесь у нас есть один экземпляр класса MyThread с двумя запущенными потоками — оба начинаются с метода run().

Бит local variables означает, что локальные переменные в методах run() (и последующих вызовах) не будут мешать друг другу в потоках (даже если они выполняются в контексте одного и того же экземпляра класса MyThread).

Например, если thread1 получает Person fred, а thread2 получает Person bill, вызов thread1 к printPerson всегда гарантирует, что desc будет описанием для fred (и аналогичным образом desc всегда будет описанием для bill в thread2).

РЕДАКТИРОВАТЬ, ЧТОБЫ ДОБАВИТЬ: В дополнение к вашему вопросу о том, что "если два потока асинхронно читают одну глобальную переменную, каждый поток содержит копию этой переменной"

Нет, потоки не содержат собственных копий объектов. Например, рассмотрим переменную экземпляра name выше.

Это переменная экземпляра MyThread. Как указывалось ранее, оба потока выполняются в контексте ОДНОГО ЭКЗЕМПЛЯРА MyThread. Это означает, что они оба обращаются к ОДНОМУ ЭКЗЕМПЛЯРУ имени. Это означает, что когда один меняет «имя», другой увидит это изменение.

В результате установка this.name и вызов doMore(this.name) таким образом — это плохо. Например, вполне возможна следующая последовательность действий:

  1. Поток 1 устанавливает для this.name значение «Привет, Фред».
  2. Поток 2 устанавливает для this.name значение «Привет, счет».
  3. Поток 1 вызывает doMore(this.name)

Это приведет к тому, что поток 1 вызовет doMore("Hello bill") , поскольку потоки обращаются к одному и тому же объекту (а не к своей собственной копии объекта).

Добро пожаловать в удивительный мир гоночных условий!

person racraman    schedule 15.01.2020