Постоянство памяти в java.util.concurrent - PullRequest
1 голос
/ 23 марта 2011

Из Свойство постоянства памяти мы знаем, что: «Действия в потоке перед помещением объекта в любую параллельную коллекцию выполняются до действий после доступа или удаления этого элемента из коллекции в другомthread. "

Означает ли это: если я создаю объект и помещаю его в ConcurrentLinkedQueue в одном потоке, другой поток увидит все свойства объекта без какой-либо другой синхронизации объекта?

Например:

public class Complex{

  int index;

  String name;

  public Complex(int index, String name){

     this.index = index;

     this.name = name;

  }

  public String getName(){

     return name;

  }

  public int getIndex(){

     return index;

  }

}

public class SharedQueue{

   public static ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue();

}

в один поток:

...........

Complex complex = new Complex(12, "Sam");

SharedQueue.queue.add(complex);

...........

в другой теме

......

Complex complex = SharedQueue.queue.poll();

System.out.printly(complex.getIndex() + ";" + complex.getName());

.............

Будет ли второй поток обязательно видеть свойства объекта complex?если второй поток извлекает объект и печатает его после того, как первый поток помещает объект в очередь.

Мы знаем, что в обычном случае мы должны синхронизировать объект в многопоточных средах, если он совместно используется.1031 *

Как

public class Complex{

  int index;

  String name;

  public Complex(int index, String name){

     this.index = index;

     this.name = name;

  }

  public synchronized String getName(){

     return name;

  }

  public synchronized int getIndex(){

     return index;

  }

}

Ответы [ 4 ]

1 голос
/ 23 марта 2011
  1. Все потоки видят все объекты, на которые они могут получить ссылку, так что да, это также относится к коллекциям.Параллельные коллекции используют синхронизацию, чтобы не разрываться, так как два или более потоков обращаются к ним одновременно (например, цикл for может прерваться), поэтому вы можете использовать их для совместного использования объектов между потоками.

  2. Если ваш объект является неизменяемым, т.е. доступным только для чтения, как ваш класс Complex, указанный выше (с добавлением окончательных модификаторов), то вам не нужно синхронизировать доступ к нему, поскольку он поточно-ориентирован.

Точка синхронизации заключается в том, чтобы гарантировать, что ваши переменные согласованы на протяжении n операций.Пример:

Если вы хотите вычислить

i = i + 2;

, то это состоит из первого чтения значения i, добавления 2, а затем установки значения обратно в i.

Теперь, если какой-то другой поток приходит и обновляет i сразу после того, как вы добавили 2, вы фактически перезаписываете это обновление, поскольку вы по-прежнему удерживаете сумму, основанную на предыдущем значении + два, устанавливая ее обратно на.

0 голосов
/ 23 марта 2011

Точно. В этом случае ConcurrentLinkedQueue работает как синхронизатор.

0 голосов
/ 23 марта 2011

Это означает, что если поток A помещает объект в коллекцию, а поток B получает его оттуда, поток B может видеть результаты любых действий, выполненных потоком A, перед помещением объекта в коллекцию (а также действия, которые произошло-до их в других темах и т. д.).Эти действия включают инициализацию объекта (если это было сделано потоком A), так что поток B может видеть объект в согласованном состоянии.

Обратите внимание, что он не предоставляет никаких гарантий относительно действий, которые произошли в потокеA после помещения объекта в коллекцию или о действиях других потоков (за исключением действий, связанных с переходным случаем-до порядка, как отмечено выше), так что вам все еще нужна синхронизация, если вы собираетесь изменить объект послепоместив его в коллекцию.

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

0 голосов
/ 23 марта 2011

JSR 133 также указывает, что поля final объекта являются полными и видимыми для всех потоков, когда конструктор завершает работу.Эта поддержка была добавлена ​​в Java 5.0 (в 2004 году).Никаких других действий не требуется, чтобы ваш объект был видимым и корректным во всех потоках.

Использование синхронизации на неизменяемом объекте ничего не дает в этом случае.

Существует множество документов, которыеуказать иное, и они, как правило, предшествуют 2004 году.;)

...