Почему Автор в своем решении для методов
get() и clear()
использует блокировки по разным объектам
synchronized (locks[hash% NUMBER_LOCKS])
synchronized (locks[i% NUMBER_LOCKS])
С моей точки зрения может возникнуть ПРОБЛЕМА - , когда мы get() получаем элемент, в этот момент другой поток может стирать clear() этот же элемент
Разве я Неправ? На каждую группу Корзин должен быть один и тот же замок по моему
public class Solution {
private static final int NUMBER_LOCKS = 12;
private final Node[] buckets;
private final Object[] locks;
static class Node {
public Node next;
public Object key;
public Object value;
}
public Solution(int numberBuckets) {
buckets = new Node[numberBuckets];
locks = new Object[NUMBER_LOCKS];
for (int i = 0; i < NUMBER_LOCKS; i++) {
locks[i] = new Object();
}
}
private final int hash(Object key) {
return Math.abs(key.hashCode() % buckets.length);
}
public Object get(Object key) {
int hash = hash(key);
synchronized (locks[hash% NUMBER_LOCKS]) {
for (Node m = buckets[hash]; m != null; m = m.next) {
if (m.key.equals(key)) return m.value;
}
}
return null;
}
public void clear() {
for (int i = 0; i < buckets.length; i++) {
synchronized (locks[i%NUMBER_LOCKS]) {
buckets[i] = null;
}
}
}
public static void main(String[] args) {
}
}
get()
совершается обращение к корзине с индексомhash
, то устанавливается лок с индексомhash % NUMBER_LOCKS
. В методеclear()
, при удалении корзины с индексомi
, устанавливается соответствующий лок с индексомi % NUMBER_LOCKS
. То есть обращение к какой-либо корзине, одновременное с удалением этой же корзины, исключается.HashMap
). В такой таблице предполагается что различные ключи могут иметь совпадающие хеши (такой случай называется коллизией). Различные ключи с одинаковыми значениями хешей, хранятся в одной структуре данных которая называется корзина. Ключи с разными хешами хранятся в разных корзинах. То есть ситуация когда в одной корзине есть ссылка на элемент другой корзины невозможна. В приведённом коде множество корзин представлено в виде массива, хранящего ссылки на корневые узлы корзин, реализованных в виде односвязных списков. Поэтому, если я правильно понимаю то, что имитирует данный код, ситуация при которой что-то происходит с элементом корзины в методеget()
и, одновременно с этим, методclear()
тоже производит действия с этим же элементом, невозможна, так как множества элементов различных корзин не пересекаются. То есть ситуация когда один и тот же узел находится одновременно в двух разных корзинах концептуально невозможна.