Мне нужен способ разрешить только одному потоку изменять данные, относящиеся к билету на обслуживание. В течение более чем одного потока может быть предпринята попытка изменить данные билета одновременно.Синхронизация потоков на основе идентификатора
Ниже приведен упрощенный вариант моего подхода. Есть лучший способ сделать это? Может быть, с пакетами java.util.concurrent?
public class SomeClass1
{
static final HashMap<Integer, Object> ticketLockMap = new HashMap<Integer, Object>();
public void process(int ticketNumber)
{
synchronized (getTicketLock(ticketNumber))
{
// only one thread may modify ticket data here
// ... ticket modifications here...
}
}
protected static Object getTicketLock(int ticketNumber)
{
Object ticketLock;
// allow only one thread to use map
synchronized (ticketLockMap)
{
ticketLock = ticketLockMap.get(ticketNumber);
if (ticketLock == null)
{
// first time ticket is locked
ticketLock = new Object();
ticketLockMap.put(ticketNumber, ticketLock);
}
}
return ticketLock;
}
}
Кроме того, если я не хочу, наполняя HashMap с неиспользуемыми замков, я бы нужен более сложный подход, как следующее:
public class SomeClass2
{
static final HashMap<Integer, Lock> ticketLockMap = new HashMap<Integer, Lock>();
public void process(int ticketNumber)
{
synchronized (getTicketLock(ticketNumber))
{
// only one thread may modify ticket data here
// ... ticket modifications here...
// after all modifications, release lock
releaseTicketLock(ticketNumber);
}
}
protected static Lock getTicketLock(int ticketNumber)
{
Lock ticketLock;
// allow only one thread to use map
synchronized (ticketLockMap)
{
ticketLock = ticketLockMap.get(ticketNumber);
if (ticketLock == null)
{
// first time ticket is locked
ticketLock = new Lock();
ticketLockMap.put(ticketNumber, ticketLock);
}
}
return ticketLock;
}
protected static void releaseTicketLock(int ticketNumber)
{
// allow only one thread to use map
synchronized (ticketLockMap)
{
Lock ticketLock = ticketLockMap.get(ticketNumber);
if (ticketLock != null && --ticketLock.inUseCount == 0)
{
// lock no longer in use
ticketLockMap.remove(ticketLock);
}
}
}
}
class Lock
{
// constructor/getters/setters omitted for brevity
int inUseCount = 1;
}
Вы должны иметь возможность использовать что-то вроде 'ConcurrentHashMap' вместо' HashMap' для блокировки билетов и избегать бит синхронизации, который плохо работает. 'putIfAbsent()' должно быть именно то, что вам нужно. – manub
@Jeff проверить эту тему http://stackoverflow.com/questions/659915/synchronizing-on-an-integer-value –