этот класс потокобезопасен? - PullRequest
4 голосов
/ 16 апреля 2010

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

public class test{

public void test1{

// do something

}

public void test2{

// do something


}

public void test3{

// do something

}



}

Ответы [ 8 ]

6 голосов
/ 16 апреля 2010

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

3 голосов
/ 16 апреля 2010

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

int incrementCount() {
    this.count++;
    // ... Do some other stuff
    return this.count;
}

не будет потокобезопасным.Почему это не так?Представьте, что поток 1 обращается к нему, count увеличивается, затем происходит некоторая обработка.Проходя через функцию, другой поток обращается к ней, снова увеличивая count.Первый поток, в котором он прошел, скажем, от 1 до 2, теперь будет иметь значение от 1 до 3, когда вернется.Поток 2 будет видеть, что он будет также переходить с 1 на 3, так что же случилось с 2?

В этом случае вы захотите что-то вроде этого (помните, что это не какой-то языковой код,но ближе всего к Java, один из 2, в которые я потянул потоки)

int incrementCount() synchronized {
    this.count++;
    // ... Do some other stuff
    return this.count;
}

Ключевое слово synchronized здесь гарантирует, что до тех пор, пока один поток обращается к нему, другие потоки не смогут.Это будет означать, что поток 1 попадает в него, count идет от 1 до 2, как и ожидалось.Поток 2 попадает в него, пока обрабатывается 1, он должен дождаться завершения потока 1.Когда это будет сделано, поток 1 получит возврат 2, затем поток 2 перестанет работать и получит ожидаемое значение 3.

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

int incrementCount(int count) {
    count++;
    // ... Do some other stuff
    return this.count;
}

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

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

2 голосов
/ 16 апреля 2010

Рассмотрим следующую цитату из статьи о безопасности потоков («Теория и практика Java: характеристика безопасности потоков»):

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

Безопасность потока

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

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

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

1 голос
/ 16 апреля 2010

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

(да, я вижу, что методы, показанные здесь, не имеют параметров, но также и скобок, так что это явно не полный рабочий код - он даже не скомпилируется как есть.)

0 голосов
/ 16 апреля 2010

Да - этот класс является потокобезопасным, но это не означает, что ваше приложение.

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

В любом практическом применении объекты будут иметь состояние. Если вы можете гарантировать, что к этим объектам нет доступа одновременно, у вас есть поточно-ориентированное приложение.

Существуют способы оптимизации доступа к общему состоянию, например, Атомарные переменные или с осторожным использованием ключевого слова volatile, но я думаю, что это выходит за рамки того, что вы просили.

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

0 голосов
/ 16 апреля 2010

Нет, я так не думаю.

Например, один из методов может получить (не ориентированный на поток) одноэлементный объект из другого класса и видоизменить этот объект.

0 голосов
/ 16 апреля 2010

Если у него нет изменяемого состояния - это потокобезопасно. Если у вас нет состояния - вы можете использовать поток по ассоциации.

0 голосов
/ 16 апреля 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...