Является ли ConcurrentSkipListMap.compute() безопасным для относительных обновлений?

В Javadoc для ConcurrentSkipListMap.compute(K, BiFunction) говорится:

Пытается вычислить сопоставление для указанного ключа и его текущего сопоставленного значения (или ноль, если текущего сопоставления нет). Функция НЕ гарантированно применяется один раз атомарно.

Я понимаю, что эта функция может вызываться несколько раз, но что означает "один раз"?

В частности, безопасно ли вызывать функцию X = X + 1 без увеличения значения карты в несколько раз?

1 ответ

Это говорит о том, что:

  • функция может быть вызвана более одного раза, и
  • эти звонки могут перекрываться во времени; т.е. если несколько потоков вызывают compute одновременно.

Другими словами, не ожидайте атомарного поведения в способе, которым ссылка на функцию вызывается compute,


В частности, безопасно ли для функции вызывать X = X + 1 без многократного увеличения значения карты?

Это зависит от того, что означает "вызвать X = X + 1". (Вы не включили четкий пример....)

  • Если x = x + 1 означает, что вы просто пытаетесь увеличить значение карты, а затем:

    • Один звонок compute приведет только к одному "приращению" из-за определения в compute в ConcurrentMap,

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

  • Если x = x + 1 относится к побочному эффекту ссылки на метод, тогда все ставки выключены:

    • Это могло случиться несколько раз.
    • Если ссылка на ваш метод не синхронизирована должным образом, и так далее, возможны всевозможные неприятные эффекты. Спецификация подразумевает, что compute Вызов не будет синхронизироваться извне или вызывать ссылку на метод в мьютексе или что-то в этом роде. Применяются нормальные правила параллелизма / памяти...
Другие вопросы по тегам