2013-06-12 3 views
3

하나의 스레드 만 서비스 티켓과 관련된 데이터를 수정할 수 있도록하는 방법이 필요합니다. 두 개 이상의 스레드가 티켓 데이터를 동시에 수정하려고 시도하고 있습니다.id 기반 스레드 동기화

아래는 간단한 접근 방식입니다. 이 작업을 수행하는 더 좋은 방법이 있습니까? 어쩌면 java.util.concurrent 패키지로? 당신은 Lock interface을 찾고 될 수

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; 
} 
+2

티켓 잠금을 위해'HashMap' 대신'ConcurrentHashMap'과 같은 것을 사용할 수 있어야하고 성능이 좋지 않은'synchronized' 비트를 피할 수 있어야합니다. 'putIfAbsent()'는 꼭 필요한 것이어야합니다. – manub

+0

@Jeff이 스레드를 확인하십시오. http://stackoverflow.com/questions/659915/synchronizing-on-an-integer-value –

답변

1

: 나는 HashMap의 사용하지 않는 자물쇠로 채우고 싶지 않은 경우

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; 
    } 
} 

또한, 나는 다음과 같은 더 복잡한 접근을해야합니다. 두 번째 경우는 잠겨있는 횟수를 세는 ReentrantLock으로 해결할 수 있습니다.

자물쇠 취득 잠금을 기다리는 .lock() 방법 및 이것을 다음 HashMap<Integer, Lock>과 결합 될 수

Lock l = ...; 
l.lock(); 
try { 
    // access the resource protected by this lock 
} finally { 
    l.unlock(); 
} 

같이 호출되어야 .unlock 방법이있다. synchronized 호출을 생략하고 코드 줄을 줄일 수 있습니다.