Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Непостоянная ошибка при работе многопоточной программы / 25 сообщений из 32, страница 1 из 2
13.01.2013, 02:18:39
    #38108078
redwhite90
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class Tester {
  
   public static void main(String[] args) throws ExecutionException, InterruptedException {
       Integer x[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
       ExecutorService service = Executors.newCachedThreadPool();
       System.out.println(service.submit(new CallableClass(x, 0, 5)).get());
       System.out.println(service.submit(new CallableClass(x, 5, 9)).get());
       service.shutdown();
   }
}

class CallableClass implements Callable<Integer> {
    Integer x[];
    int index1;
    int index2;

    CallableClass(Integer[] x, int index1, int index2) {
        this.x = x;
        this.index1 = index1;
        this.index2 = index2;
    }

    public Integer call() {
        int sum = 0;
        for (int i = index1; i < index2; i++)
            sum += x[i];
        return sum;
    }
}



Иногда программа правильно выполняется, а иногда вываливается ошибка windows:
автор00005
Смещение исключения: 000000000009970a
Версия ОС: 6.1.7601.2.1.0.256.1
Код языка: 1049
Дополнительные сведения 1: 4c0d
Дополнительные сведения 2: 4c0d4d78887f76d971d5d00f1f20a433
Дополнительные сведения 3: 4c0d
Дополнительные сведения 4: 4c0d4d78887f76d971d5d00f1f20a433

вываливается 1 раз на 10 запусков в среднем
...
Рейтинг: 0 / 0
13.01.2013, 09:28:26
    #38108110
Basil A. Sidorov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
redwhite90Иногда программа правильно выполняется, а иногда вываливается ошибка windows:автор00005
Смещение исключения: 000000000009970a
Версия ОС: 6.1.7601.2.1.0.256.1
Код языка: 1049
Дополнительные сведения 1: 4c0d
Дополнительные сведения 2: 4c0d4d78887f76d971d5d00f1f20a433
Дополнительные сведения 3: 4c0d
Дополнительные сведения 4: 4c0d4d78887f76d971d5d00f1f20a433вываливается 1 раз на 10 запусков в среднем1. При падениях JVM должен создаваться дамп стека и записываться, вместе с дополнительной информацией, в лог-файл.
2. Логировать не пробовали?
...
Рейтинг: 0 / 0
13.01.2013, 12:09:43
    #38108139
irbis_al
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
Привет.
Рассмотрите проблему в
service.shutdown();

Ведь он може быть вызван пока не отработано service.submit
System.out.println(service.submit(new CallableClass(x, 0, 5)).get());
...
Рейтинг: 0 / 0
13.01.2013, 21:22:42
    #38108491
_quark_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
redwhite90...
Integer x[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
...


эта переменная должна быть finall - вы же её в другой поток передаете.
...
Рейтинг: 0 / 0
13.01.2013, 22:15:54
    #38108542
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
_quark_эта переменная должна быть finall - вы же её в другой поток передаете.
LOL. Ничего что она локальная? И сама переменная не модифицируется.
...
Рейтинг: 0 / 0
14.01.2013, 10:36:50
    #38108838
ivanra
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
Ну, во-первых, хотя программа и многопоточная, выполняться она будет строго последовательно.
Во-вторых, ошибки вроде быть не должно, возможно, проблема в конкретной версии jvm, уточните, что используете
...
Рейтинг: 0 / 0
14.01.2013, 14:58:53
    #38109337
_quark_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
ivanraНу, во-первых, хотя программа и многопоточная, выполняться она будет строго последовательно.
Во-вторых, ошибки вроде быть не должно, возможно, проблема в конкретной версии jvm, уточните, что используете

Почему это? Насколько я понимаю тут будет 3 потока: 1 основной и по одному для каждого задания

Blazkowicz_quark_эта переменная должна быть finall - вы же её в другой поток передаете.
LOL. Ничего что она локальная? И сама переменная не модифицируется.

В том то и дело, что она локальная. Модель памяти Java не гарантирует, что x[] будет инициализирована раньше, чем начнут выполнятся новые потоки.
finall это гарантирует. Почитайте Java Concurrency in Practice - узнаете много нового.
...
Рейтинг: 0 / 0
14.01.2013, 15:07:37
    #38109367
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
_quark_В том то и дело, что она локальная.

Вы наверное про поле CallableClass ?

_quark_Модель памяти Java не гарантирует, что x[] будет инициализирована раньше, чем начнут выполнятся новые потоки.

Мгу. Зато она гарантирует что выполнение конструктора будет закончено до вызова метода submit().

_quark_finall это гарантирует. Почитайте Java Concurrency in Practice - узнаете много нового.
Здесь гонок нет. Если даёте ссылку то давайте на конкретную главу, хотя бы. А так пальцем в небо. Читал. Узнал много нового. Как это применяется к указанному коду?
...
Рейтинг: 0 / 0
14.01.2013, 15:17:45
    #38109398
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
_quark_В том то и дело, что она локальная. Модель памяти Java не гарантирует, что x[] будет инициализирована раньше, чем начнут выполнятся новые потоки.
finall это гарантирует. Почитайте Java Concurrency in Practice - узнаете много нового.

Вот здесь описано например.
http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#finalRight
Значения поля, действительно, можно не увидеть в другом потоке, если поле не final и конструктор предоставляет ссылку на экземпляр другому потоку до окончания выполнения конструктора .
Т.е. другой поток должен получит ссылку на CallableClass, до окончания выполнения CallableClass<init>. Чего в данном примере не наблюдается.
...
Рейтинг: 0 / 0
14.01.2013, 15:41:42
    #38109458
_quark_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
BlazkowiczВы наверное про поле CallableClass ?
Нет я имел ввиду именно локальную переменную x метода main. А именно то, что она может передаться новым потокам непроинициализированной.

Blazkowicz_quark_finall это гарантирует. Почитайте Java Concurrency in Practice - узнаете много нового.
Здесь гонок нет. Если даёте ссылку то давайте на конкретную главу, хотя бы. А так пальцем в небо. Читал. Узнал много нового. Как это применяется к указанному коду?

Глава 3.5. Safe Publication

3.5.1. Improper Publication: When Good Objects Go Bad
You cannot rely on the integrity of partially constructed objects. An observing thread could see the object in an inconsistent state, and then later see its state suddenly change, even though it has not been modified since publication.

In fact, if the Holder in Listing 3.15 is published using the unsafe publication idiom in Listing 3.14, and a thread other than the publishing thread were to call assertSanity, it could throw AssertionError![15]

[15] The problem here is not the Holder class itself, but that the Holder is not properly published. However, Holder can be made immune to improper publication by declaring the n field to be final, which would make Holder immutable; see Section 3.5.2.

Listing 3.15. Class at Risk of Failure if Not Properly Published.
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
public class Holder {
   private int n;
   public Holder(int n) { this.n = n; }
   public void assertSanity() {
      if (n != n)
      throw new AssertionError("This statement is false.");
   }
}



Because synchronization was not used to make the Holder visible to other threads, we say the Holder was not properly published. Two things can go wrong with improperly published objects. Other threads could see a stale value for the holder field, and thus see a null reference or other older value even though a value has been placed in holder. But far worse, other threads could see an up to date value for the holder reference, but stale values for the state of the Holder. [16] To make things even less predictable, a thread may see a stale value the first time it reads a field and then a more up to date value the next time, which is why assertSanity can throw AssertionError.

[16] While it may seem that field values set in a constructor are the first values written to those fields and therefore that there are no "older" values to see as stale values, the Object constructor first writes the default values to all fields before subclass constructors run. It is therefore possible to see the default value for a field as a stale value.

At the risk of repeating ourselves, some very strange things can happen when data is shared across threads without sufficient synchronization.

...

3.5.2. Immutable Objects and Initialization Safety

...

To publish an object safely, both the reference to the object and the object's state must be made visible to other threads at the same time. A properly constructed object can be safely published by:
Initializing an object reference from a static initializer;

Storing a reference to it into a volatile field or AtomicReference;

Storing a reference to it into a final field of a properly constructed object; or

Storing a reference to it into a field that is properly guarded by a lock.


В данном случае локальная переменная x метода main как раз публикуется (передается конструкторам CallableClass) не безопасно. Поэтому другие потоки могут увидеть её в непроинициализированном состоянии. final обеспечивает безопасную публикацию.
...
Рейтинг: 0 / 0
14.01.2013, 15:51:34
    #38109478
забыл ник
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
в данном случае отвественность за безопасную публикацию берет на себя ExecutorService.

ТС, а ты случайно не на шаред хостинге это все гоняешь? Помню у меня были дикие траблы когда я разворачивал приложение на VPS с системой виртуализации OpenVZ, как раз в случае многопоточных программ. Пока писал, понял что сморозил глупость - у тебя же венда:)
...
Рейтинг: 0 / 0
14.01.2013, 16:03:59
    #38109511
_quark_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
забыл никв данном случае отвественность за безопасную публикацию берет на себя ExecutorService.

ExecutorService берет на себя ответственность за безопасную публикацию только экземпляров CallableClass. Локальная переменная x метода main опубликована небезопасно - поэтому значением поля x экземпляров CallableClass потоки могут увидеть самые странные значения.
...
Рейтинг: 0 / 0
14.01.2013, 16:19:50
    #38109551
забыл ник
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
_quark_забыл никв данном случае отвественность за безопасную публикацию берет на себя ExecutorService.

ExecutorService берет на себя ответственность за безопасную публикацию только экземпляров CallableClass. Локальная переменная x метода main опубликована небезопасно - поэтому значением поля x экземпляров CallableClass потоки могут увидеть самые странные значения.

Угу, сразу после конструирования, которое идет после инициализации массива, и оба действия происходят в одном потоке, сохраняя при этом total order of execution. Этакий piggybacking.
...
Рейтинг: 0 / 0
14.01.2013, 16:48:42
    #38109608
_quark_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
забыл никУгу, сразу после конструирования, которое идет после инициализации массива, и оба действия происходят в одном потоке, сохраняя при этом total order of execution. Этакий piggybacking.

Именно. Модель памяти java при многопоточности так и работает. Потоки задач уже могут выполнять CallableClass.call(), а локальная переменная x метода main может быть все-еще непроинициализированна.
...
Рейтинг: 0 / 0
14.01.2013, 16:58:12
    #38109632
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
_quark_Глава 3.5. Safe Publication
3.5.2. Immutable Objects and Initialization Safety

Речь исключительно о полях и объектах. Ни слова о локальных переменных и массивах. И это тоже самое на что я привел ссылку выше.

_quark_В данном случае локальная переменная x метода main как раз публикуется

Ну, начинается - "локальная переменная публикуется". Публикуются объекты, а не переменные. Публикуется массив. По вашему этот массив может быть не до конца инициализирован? Или в чем проявляется unsafe publication?

_quark_(передается конструкторам CallableClass) не безопасно. Поэтому другие потоки могут увидеть её в непроинициализированном состоянии. final обеспечивает безопасную публикацию.
Дальнейшие рассуждение смысла не имеют, так как вы переменную от объекта не отличаете. Попробуйте сформулировать кто именно и как именно здесь публикуется не безопасно в терминах экземпляров. Тогда обсудим.
...
Рейтинг: 0 / 0
14.01.2013, 17:09:13
    #38109649
schwa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
_quark_В данном случае локальная переменная x метода main как раз публикуется (передается конструкторам CallableClass) не безопасно. Поэтому другие потоки могут увидеть её в непроинициализированном состоянии. final обеспечивает безопасную публикацию.
И почему тогда вот этот Holder публикуется не безопасно?
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
public class Holder {
   private int n;
   public Holder(int n) { this.n = n; }
   public void assertSanity() {
      if (n != n)
      throw new AssertionError("This statement is false.");
   }
}


Ведь можно делать так и ...
Код: java
1.
2.
3.
final int n = ....
....
//а дальше передаем n в созданный инстанс Holder-а 


и все состояние Holder-а безопасно опубликовано.
...
Рейтинг: 0 / 0
14.01.2013, 17:11:11
    #38109651
_quark_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
BlazkowiczПо вашему этот массив может быть не до конца инициализирован?
Да.

BlazkowiczРечь исключительно о полях и объектах.
Массив x это объект (аналогично экземпляру класса Holder из примера). Потоки заданий могут увидеть его в непроинициализированном состоянии.
...
Рейтинг: 0 / 0
14.01.2013, 17:19:58
    #38109660
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
_quark_Потоки задач уже могут выполнять CallableClass.call(), а локальная переменная x метода main может быть все-еще непроинициализированна.
"непроинициализировання" переменная это ссылка на null. Т.е по вашему локальная переменная на стеке, вместо ссылки на массив будет почему-то содержать ссылку на null? И этот null будет использован при вызове конструктора CallableClass в том же методе?
Звучит как бред?

Или речь таки об инициализации массива и его публикации? Т.е. массив может быть не заполнен? Но как это связано с финальностью локальной переменной?
...
Рейтинг: 0 / 0
14.01.2013, 17:21:04
    #38109663
_quark_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
schwa_quark_В данном случае локальная переменная x метода main как раз публикуется (передается конструкторам CallableClass) не безопасно. Поэтому другие потоки могут увидеть её в непроинициализированном состоянии. final обеспечивает безопасную публикацию.
И почему тогда вот этот Holder публикуется не безопасно?
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
public class Holder {
   private int n;
   public Holder(int n) { this.n = n; }
   public void assertSanity() {
      if (n != n)
      throw new AssertionError("This statement is false.");
   }
}


Ведь можно делать так и ...
Код: java
1.
2.
3.
final int n = ....
....
//а дальше передаем n в созданный инстанс Holder-а 


и все состояние Holder-а безопасно опубликовано.

В примере Holder вообще не публикуется.
Публикация происходит тогда, когда экземпляр класса Holder будет передается другому потоку.
Если вы опубликуете объект класса Holder безопасно - то все будет ОК. Если нет, то другой поток может увидеть этот объект в состоянии, когда выполнение конструктора этого объекта в основном потоке еще не закончилось.
...
Рейтинг: 0 / 0
14.01.2013, 17:22:11
    #38109665
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
_quark_BlazkowiczПо вашему этот массив может быть не до конца инициализирован?
Да.

Но final таки влияет на состояние самой ссылки. На процесс инициализации элементова массива он никак не влияет.


_quark_Массив x это объект (аналогично экземпляру класса Holder из примера). Потоки заданий могут увидеть его в непроинициализированном состоянии.
Т.е. некоторые элементы будут null? Вы это хотите сказать?
...
Рейтинг: 0 / 0
14.01.2013, 17:27:12
    #38109672
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
schwaИ почему тогда вот этот Holder публикуется не безопасно?

Там говорится что проблема не в самом holder, а в том что если он публикуется не безопасно, то значение n может быть не проинициализированым.
...
Рейтинг: 0 / 0
14.01.2013, 17:31:40
    #38109682
_quark_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
Blazkowicz_quark_Потоки задач уже могут выполнять CallableClass.call(), а локальная переменная x метода main может быть все-еще непроинициализированна.
"непроинициализировання" переменная это ссылка на null. Т.е по вашему локальная переменная на стеке, вместо ссылки на массив будет почему-то содержать ссылку на null? И этот null будет использован при вызове конструктора CallableClass в том же методе?
Звучит как бред?
Еще веселее. Т.к. локальные переменные не инициализируются значениями по умолчанию, то локальная переменная x может содержать ссылку на "недостроенный" массив (т.е. этот самый массив может как раз инициализироваться основным потоком, когда поток задачи к нему обращается).

BlazkowiczИли речь таки об инициализации массива и его публикации? Т.е. массив может быть не заполнен? Но как это связано с финальностью локальной переменной?
С final фича в том, что если локальную переменную x объявить finall , то она сначала проинициализируется, а уже только потом эта переменная будет использоваться в new CallableClass(x, 0, 5).
...
Рейтинг: 0 / 0
14.01.2013, 17:43:25
    #38109704
забыл ник
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
_quark_,

Вы не правы в данном случае.

Рассмотрим по порядку -
1) идет инициализация массива и присваивание переменной ссылки на него
2) идет конструирование Callable в ТОМ же потоке, модель памяти java гарантирует что компилятор никак не должен ломать total execution of order внутри исполнения ОДНОГО потока, таким образом Callable будет гарантировано сконструирован правильно.
3) Далее мы ложим Callable в экзекьютор и экзекьютор сам уже заботится о публикации ссылки на Callable
Таким образом код абсолютно корректен. А вот если бы массив был параметром к методу, или полем класса - тогда да, возможны варианты, потому что непонятно в каком потоке он был создан.
...
Рейтинг: 0 / 0
14.01.2013, 17:47:04
    #38109711
schwa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
_quark_schwaпропущено...

И почему тогда вот этот Holder публикуется не безопасно?
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
public class Holder {
   private int n;
   public Holder(int n) { this.n = n; }
   public void assertSanity() {
      if (n != n)
      throw new AssertionError("This statement is false.");
   }
}


Ведь можно делать так и ...
Код: java
1.
2.
3.
final int n = ....
....
//а дальше передаем n в созданный инстанс Holder-а 


и все состояние Holder-а безопасно опубликовано.

В примере Holder вообще не публикуется.
Публикация происходит тогда, когда экземпляр класса Holder будет передается другому потоку.
Если вы опубликуете объект класса Holder безопасно - то все будет ОК. Если нет, то другой поток может увидеть этот объект в состоянии, когда выполнение конструктора этого объекта в основном потоке еще не закончилось.
И каким тут образом тогда в примере из стартового сообщения получается небезопасная публикация содержимого массива, если состояние коллабл, публикуется безопасно экзекутором?
...
Рейтинг: 0 / 0
14.01.2013, 17:48:15
    #38109715
_quark_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Непостоянная ошибка при работе многопоточной программы
BlazkowiczНо final таки влияет на состояние самой ссылки. На процесс инициализации элементова массива он никак не влияет.
Как раз таки влияет, но именно при инициализации. Если после один из элементов массива будет изменен в одном из потоков, то другие потоки могут продолжить видеть старое содержимое массива.

Опять же в Java Concurrency in Practice это описывается в Chapter 16. The Java Memory Model. Есть так называемые правила happens before

16.2.2. Safe Publication
The safe publication idioms described in Chapter 3 ensure that the published object is visible to other threads because they ensure the publication happens before the consuming thread loads a reference to the published object.

если переменную локальную переменную x объявить finall, то тем самым мы её безопасно опубликуем для потоком задач и таким образом потоки гарантированно будут видеть её в проинициализированном состоянии.
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Непостоянная ошибка при работе многопоточной программы / 25 сообщений из 32, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]