Как обеспечить потокобезопасность статического метода утилиты?
есть ли какой-либо общий способ или правила выхода, с помощью которых мы можем обеспечить потокобезопасность статических методов, специально используемых в различных классах утилит любых приложений. Здесь я хочу конкретно указать на безопасность потоков веб-приложений.
хорошо известно, что статические методы с неизменяемыми объектами в качестве параметров потокобезопасны, а изменяемые объекты-нет.
если у меня есть метод утилиты для некоторых манипуляций java.util.Date
и этот метод принимает пример java.util.Date
, тогда этот метод не будет потокобезопасным. Затем как сделать его потокобезопасным без изменения способа передачи параметров?
public class DateUtils {
public static Date getNormalizeDate(Date date) {
// some operations
}
}
также является класс javax.faces.context.FacesContext
Мутабельный? Безопасно ли передавать экземпляр этого класса такому статическому методу утилиты?
этот список классов, экземпляры которых могут быть или не могут быть переданы в качестве параметров, можно долго; так что моменты должны иметь в виду при написании кодов такие классы?
5 ответов
хорошо известно, что статические методы с неизменяемыми объектами в качестве параметров являются потокобезопасными, а изменяемые объекты-нет.
Я бы оспорил это. Аргументы, переданные методу, хранятся в стеке, который является идиомой для каждого потока.
Если ваш параметр является изменяемым объектом, таким как Date
тогда вам нужно убедиться, что другие потоки не изменяют его в то же время в другом месте. Но это совсем другое дело, не связанное с безопасностью ваших нитей. метод.
метод, который вы разместили, является потокобезопасным. Он не поддерживает никакого состояния и действует только на основе своих аргументов.
я настоятельно рекомендую вам прочитать параллелизм Java на практике или аналогичная книга, посвященная безопасности потоков в Java. Это сложный вопрос, который нельзя решить соответствующим образом с помощью нескольких ответов StackOverflow.
поскольку ваш класс не содержит переменных-членов, ваш метод не имеет состояния (он использует только локальные переменные и аргумент) и поэтому является потокобезопасным.
код, который вызывает его, может быть не потокобезопасным, но это другое обсуждение. Например, дата не является потокобезопасной, если вызывающий код считывает дату, записанную другим потоком, необходимо использовать правильную синхронизацию в коде записи и чтения даты.
учитывая структуру JVM, локальные переменные, параметры метода и возвращаемые значения по своей сути являются "потокобезопасными"."Но переменные экземпляра и переменные класса будут только потокобезопасными, если вы создадите свой класс соответствующим образом. больше здесь
Я бы рекомендовал создать копию этого (изменяемого) объекта, как только начнется метод, и использовать копию вместо исходного параметра.
что-то вроде этого
public static Date getNormalizeDate(Date date) {
Date input = new Date(date.getTime());
// ...
}
вот как я думаю об этом: представьте себе лагерь (это статический метод). Как турист, я могу принести кучу объектов в моем рюкзаке (это аргументы, переданные в стеке). Кемпинг предоставляет мне место, чтобы поставить палатку и печь и т. д., Но если единственное, что делает кемпинг, - это позволяет мне изменять мои собственные объекты, то это threadsafe. Кемпинг может даже создавать вещи из воздуха (FirePit firepit = new FirePit();
), которые также создаются на стеке.
в любое время я могу исчезни вместе со всеми моими вещами в рюкзаке, и может появиться кто-то из других отдыхающих, делая в точности то, что они делали в прошлый раз, когда исчезли. Различные потоки в этом кемпинге не будут иметь доступа к объектам в стеке, созданном кемпингом в других потоках.
скажем, что есть только одна campStove (один объект CampStove, а не отдельные экземпляры). Если по какой-то части воображения я разделяю объект CampStove, то есть многопоточные соображения. Я не хочу включать свою походную плиту, исчезать, а затем появляться после того, как ее выключит какой - нибудь другой турист-я всегда буду проверять, готов ли мой хот-дог, и никогда не будет. Вы должны были бы поместить некоторую синхронизацию где-то... в классе CampStove, в методе, который вызывал кемпинг, или в самом кемпинге... а как Дункан Джонс говорит: "это другое дело".
обратите внимание, что даже если мы были кемпингом в отдельных экземплярах non-статические объекты кемпинга, совместное использование campStove будет иметь те же многопоточные соображения.