У меня есть приложение, которое многопоточно и работает нормально. Тем не менее, он сталкивается с проблемами блокировки блокировок (проверяется моментальным снимком java-стека и видит, что ждет).
Каждый поток расходует объекты из списка и либо отклоняет их, либо помещает в Bin.
Бункты изначально нулевые, поскольку каждый из них может быть дорогим (и потенциально может быть лот).
Код, вызывающий конфликт, выглядит примерно так:
public void addToBin(Bin[] bins, Item item) {
Bin bin;
int bin_index = item.bin_index
synchronized(bins) {
bin = bins[bin_index];
if(bin==null) {
bin = new Bin();
bins[bin_index] = bin;
}
}
synchronized(bin) {
bin.add(item);
}
}
Именно синхронизация в массиве bins
является узким местом.
Мне было предложено коллегой использовать двойную проверку блокировки, чтобы решить эту проблему, но мы не уверены, что именно будет сделано для обеспечения безопасности. Предлагаемое решение выглядит следующим образом:
public void addToBin(Bin[] bins, Item item) {
int bin_index = item.bin_index
Bin bin = bins[bin_index];
if(bin==null) {
synchronized(bins) {
bin = bins[bin_index];
if(bin==null) {
bin = new Bin();
bins[bin_index] = bin;
}
}
}
synchronized(bin) {
bin.add(item);
}
}
Это безопасно и/или есть лучший/более безопасный/более идиоматический способ сделать это?