2017-02-15 26 views
1

В соответствии с тем, что я прочитал о многопоточности, если вы хотите создать безопасный класс потоков, состоящий из небезопасных классов с изменяемыми потоками, вам нужно сделать защитные копии измененных объектов, переданных конструктору, чтобы, если некоторые из них изменяются впоследствии вы сохраняете исходную версию в созданном объекте. Пример:Оборонительное копирование достаточно, чтобы создать неизменяемые потокобезопасные классы из изменчивых потоков, небезопасных?

import java.util.Date; 

public class Person { 
    private final String name; 
    private final Date birthDate; 
    ... 
    public Person(final String name, final Date birthDate, ...) { 
     this.name = name; 
     this.birthDate = new Date(birthDate.getTime()); 
     ... 
    } 
    ... 
} 

Возможен ли для какого-то другой потока, чтобы изменить дату рождения, переданную в конструктор после конструкторы вызывается, но до того, как оборонительная копия сделана?

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

Это не противоречит одному из определений безопасного класса потока, который утверждает, что класс является потокобезопасным, если он ведет себя корректно в многопоточной среде без какой-либо дополнительной синхронизации со стороны своих клиентов?

Есть ли другой способ обеспечения безопасности потоков?

+1

Зачем это не быть потокобезопасным? Только один поток инициализирует объект. –

+0

Вы указали одно ограничение стратегии «копировать объект» для обеспечения безопасности потоков. Это слишком широкий ответ, чтобы упомянуть все другие решения для обеспечения безопасности потоков в этом случае. – ControlAltDel

+1

@ Параметр DateAndrewJenkins не является неизменным. – ControlAltDel

ответ

1

Да, теоретически, дата рождения, переданная в результате, может быть изменена между вызовом конструктора Person и защитной копией. Это предполагает, что это значение birthDate не было иначе потокобезопасным. Обычно, если вы беспокоились об этом, вы бы поставили вокруг него блок синхронизации, чтобы не допустить такого безумия. Поскольку эта синхронизация будет распространяться и на конструктор Person, вам будет хорошо защищена.

Вам нужно будет только синхронизировать вокруг вызова конструктора. После того, как он был создан, существует защитная копия, а другие методы Person являются потокобезопасными.

Безопасность потоков может быть достигнута многими способами - защитная копия, синхронизация, использование пакета javax.concurrency или просто правильный дизайн. Все они имеют недостатки, которые нужно понимать.

1

Возможно ли для какой-то другой поток, чтобы изменить дату рождения передается конструктору после того, как конструктор вызывается, но до сделана оборонительный копия?

Да, возможно.

Если да, то не код вызова конструктора необходимо обеспечить , что переданная дата рождения не изменяется, а конструктор выполняет?

Да, он должен, если вы звоните Person конструктор из нескольких потоков, т.е. вместо обмена создается экземпляр, вы создаете экземпляры из разных потоков. По-моему, обычно это редко.

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

Я думаю, НЕТ поскольку поточно-класс обычно означает, что вы можете перейти на правильно построенной, например из поточно-класса на несколько потоков, то есть вы будете создавать экземпляры в какой-то мастер резьбы сначала вы будете использовать тот же экземпляр во многих подчиненных/дочерних/зависимых потоках, чтобы правильно называть его бизнес-методы. Если вы не следуете этому дизайну, вы можете использовать synchronization около Person конструктор i.e. Конечно, защитного копирования будет недостаточно.

Безопасность нитей обычно означает, что любые бизнес-методы этого класса могут быть вызваны из разных потоков, и это приведет к правильному поведению и предполагает, что объект уже построен, что означает, что вам придется использовать синхронизацию в этих бизнес-методах Person класс, так как он имеет изменяемое состояние.

Оборонительная копия просто освобождая Person класс от Date объекта, созданного еще где за пределами Person класса, и это все бизнес-методы должны правильно синхронизировать себя.

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

Общая точка параллелизма Единый общий экземпляр.

Надеюсь, это поможет!