Остается ли программа правильной, когда я удаляю одну из двух летучих?
У меня есть этот упрощенный фрагмент кода с двумя переменными (предположим, что мы должны сохранить оба поля):
volatile boolean hasParam;
volatile String param;
boolean hasParam() {
if (param == null) {
getParam();
}
return hasParam;
}
String getParam() {
String tmp = param;
if (tmp == null) {
tmp = "String";
hasParam = true;
param = tmp;
}
return tmp;
}
Я размышляю, могу ли я отказаться от объявления поля таким образом: если есть два потока, вызывающих под гонкой, и первый записывает в volatile поле (делает освобождение хранилища), а второй поток читает ненулевое значение из того же поля ( делая получение чтения ) тогда он должен читать и только из . В противоположном случае ( приобретение чтения читаетnull
) второй поток пишетtrue
вparam
и возвращает его изhasParam()
.
Основываясь на этом предположении, я предполагаю, что могу безопасно удалить ключевое слово из объявления поля.
Чтобы доказать это, я разработал этот тест на основе JCStress:
@State
@JCStressTest
@Outcome(id = "true, String", expect = ACCEPTABLE, desc = "Boolean value was flushed")
@Outcome(id = "false, String", expect = FORBIDDEN, desc = "Boolean value was not flushed")
public class ConcurrencyTest {
Value value = new Value();
@Actor
public void actor1(ZL_Result r) {
r.r1 = value.hasParameter();
r.r2 = value.param;
}
@Actor
public void actor2(ZL_Result r) {
r.r1 = value.hasParameter();
r.r2 = value.param;
}
static class Value {
volatile boolean hasParam;
volatile String param;
boolean hasParameter() {
if (param == null) {
getParam();
}
return hasParam;
}
String getParam() {
String tmp = param;
if (tmp == null) {
tmp = "String";
hasParam = true;
param = tmp;
}
return tmp;
}
}
}
Этот тест дает результаты:
RESULT SAMPLES FREQ EXPECT DESCRIPTION
false, String 0 0,00% Forbidden Boolean value was not flushed
true, String 638 164 992 100,00% Acceptable Boolean value was flushed
Если я сотру изhasParam
field, то я получаю те же результаты (я предполагаю, что это доказывает правильность моего предположения):
RESULT SAMPLES FREQ EXPECT DESCRIPTION
false, String 0 0,00% Forbidden Boolean value was not flushed
true, String 1 074 450 432 100,00% Acceptable Boolean value was flushed
И если я сотруvolatile
из объявления обоих полей тест завершается неудачно:
RESULT SAMPLES FREQ EXPECT DESCRIPTION
false, String 1 420 423 0,12% Forbidden Boolean value was not flushed
true, String 1 164 432 249 99,88% Acceptable Boolean value was flushed
Итак, у меня есть два вопроса:
- Правильно ли мое предположение и программа остается правильной?
- Верен ли мой тест?