2014-07-19 2 views
0

У меня есть объект, который содержит некоторые примитивные переменныебезопасность потоков Java и примитивы

public class Myobject { 
    public final double d 
    public long a 
} 

все эти объекты будут храниться в наборе, который не синхронизирован

private Set<Myobject> myset = new HashSet<>() 

теперь я хочу, чтобы передать эти объекты в другой поток и выполнить некоторые вычисления. в этом потоке я буду читать только переменные «d» и «a», varibales никогда не будет изменен мой вопрос в том, является ли потокобезопасным создание немодифицируемого набора Collections.unmodifiableset (myset); и передать его ко второй резьбе.

+1

За исключением особых случаев, безопасность потоков является проблемой только в том случае, если вы хотите что-то изменить во время использования в нескольких потоках. – immibis

+0

Ну, в чем вас беспокоит? Если переменные никогда не будут изменены, есть ли причина, по которой '' 'не' final'? Вы переопределяете 'equals' и' hashCode'? Я бы настоятельно рекомендовал * не * сделать поля общедоступными, кстати. –

+1

Это безопасно, если вы запустите другой поток (вызовите 'Thread.start()') из того же потока, который инициализировал набор объектов после их инициализации (так как вызов 'Thread.start()' имеет отношение before-before с первой инструкцией запуска потока) –

ответ

0

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

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

+3

Это неверно. Если код во втором потоке, который читает эти объекты, не имеет отношения «до-прежде» с кодом, заполняющим набор, то второй поток может видеть пустой набор, набор с меньшим количеством объектов, сломанный набор, объекты, которые только частично инициализированы и т. д. и т. д. и т. д. –

+0

вы явно не прочитали вопрос - он прямо сказал «я хочу передать эти объекты», что в значительной степени является гарантией того, что объекты инициализируются/создаются ДО того, как они передаются с момента прохождения CREATOR их. – specializt

+2

@specializt У этого до сих пор нет отношений, связанных с отношениями. Ясно, что люди могут прочитать вопрос и по-прежнему не согласны с вами. – fgb

3

У вас есть два основных варианта, чтобы безопасно опубликовать ссылку на корневой объект графа:

  • убедитесь, что нить, которая делает строительство объекта графа является тот, который начинается (все) ребенок поток (ы), который будет использовать его;

  • напишите ссылку на полностью построенный граф объектов на изменчивую переменную.

Оба подхода обеспечить происходит, прежде, чем отношения между всеми межпоточной store действия, которые были выполнены при строительстве вашего графа объектов и все межпоточной load действия, другой поток будет выполняющийся на одном графике , Поскольку первое межпотоковое действие гарантируется как load (чтение корневой ссылки), это означает, что происходит до для всех действий store другой нити. Таким образом, он является нитевидным для чтения и записи объекта в другом потоке — до тех пор, пока он другой нить, а не одна из других тем.

В качестве стандартной меры предосторожности я включить эти цитаты из JLS, §17.4.4:

  • Записи в летучем переменной v (§8.3.1.4) синхронизирует-с всех последующего чтением v любыми thread (где «последующий» определяется в соответствии с порядком синхронизации).

  • Действие, которое запускает нить, синхронизируется с первым действием в потоке, которое оно запускает.

+0

Это неправильно. Существуют и другие средства безопасной публикации. – Raedwald

+1

@ Raedwald Можете ли вы объяснить «неправильную» часть? Я знаю, что есть и другие средства, но это вполне законные средства, рекомендованные самой JLS. И я специально подчеркнул, что это два * основных * варианта. –

1

Нет, создавая неизменяемый Колле ние недостаточно.Вы должны убедиться, что поток, который строит (и/изменяет) объект , безопасно публикует объект в поток, который его читает. Есть несколько способов сделать это. Некоторые из них довольно сложны, чтобы получить право. Самый простой способ получить это право - иметь объект блокировки и синхронизировать потоки ботов при блокировке при записи, конструируя или.

+0

+1 Это правильно, хотя можно утверждать, какой путь самый простой. Просто замена закрывающей скобки синхронизированного блока, о которой вы упоминаете при назначении переменной volatile, - это все, что требуется для правильной работы безопасной публикации волатильной. Сторона чтения не имеет никаких ограничений - никакие блокировки для приобретения (или не забудьте сделать это). –

Смежные вопросы