2014-09-25 2 views
1

моя проблема в том, что я хочу блокировку на основе пользователя, которую я могу создать в одном потоке и выпускать в другом потоке. Я пытался использовать блокировочные замки, но моя идея никуда не делась.Основанная на основе Reentrant Lock в Java

I.e. Есть синие, зеленые и фиолетовые люди. В каждой цветовой группе есть только одна лопата. Если фиолетовой группе необходимо использовать лопату, им нужно ждать, пока лопата будет доступна. И синяя группа, и фиолетовая группа могут иметь соответствующие лопаты в данный момент.

MainClass

public class MainReentrant { 

    public static ConcurrentHashMap<String, ReentrantLock> locks; 

    public static void main(String[] args){ 

      locks = new ConcurrentHashMap<String, ReentrantLock>(); 

      new Thread(new ReentrantEx(1)).start();; 
      new Thread(new ReentrantEx(1)).start();; 
      new Thread(new ReentrantEx(2)).start();; 

    } 
} 

Первый шаг заключается в создании блокировки и блокировки.

public class ReentrantEx implements Runnable { 
    private Integer id; 

    public ReentrantEx(Integer id){ 
     this.id = id; 
    } 
    public void doSomethingPerUser(Integer i){ 
     synchronized(i){ 
      ReentrantLock tempLock = MainReentrant.locks.get(i.toString()); 

      if(tempLock != null){ 
       //we have an unlocked lock 
       tempLock.lock(); 
      }else{ 
       //add a new lock for this customer 
       tempLock = new ReentrantLock(); 
       tempLock.lock(); 
       MainReentrant.locks.put(i.toString(), tempLock); 
      } 

      System.out.println("doSomethingPerUser lock should be held : " + i); 

      new Thread(new RandomRunnable(i)).start(); 

     } 
    } 
    @Override 
    public void run() { 
     // TODO Auto-generated method stub 
     doSomethingPerUser(id); 

    } 
} 

Далее randomRunnable класс пытается освободить замок, созданного ReentrantEx

public class RandomRunnable implements Runnable { 

    private Integer id; 
    public RandomRunnable(Integer id){ 
     this.id = id; 
    } 

    @Override 
    public void run() { 
     // TODO Auto-generated method stub 

     System.out.println(" RandomRunnable: id = "+ id); 

     ReentrantLock tempLock = MainReentrant.locks.get(id.toString()); 

     synchronized(tempLock){ 
      if(tempLock == null){ 
       System.out.println("ERROR: we have a lock that we cannot free"); 
       return; 
      }else{ 
       tempLock.unlock(); 
       //ReentrantEx.locks.put(id.toString(), tempLock); 
      } 
     } 
    } 

} 

Всякий раз, когда я делаю это я получаю этих роды ошибки:

Exception in thread "Thread-5" java.lang.IllegalMonitorStateException 
    at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:127) 
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1239) 
    at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:431) 
    at test.RandomRunnable.run(RandomRunnable.java:25) 
    at java.lang.Thread.run(Thread.java:695)  

здесь является хорошей ссылкой на замки в целом ... locks

ответ

4

Проще говоря, ReentrantLock не для вас. Субъект, занимающий блокировку, является нитью , поэтому, когда вы пытаетесь отпустить его в другом потоке, этот поток на самом деле пытается освободить блокировку, которой он не владеет. Тем временем поток, который его приобрел, держится за него.

Возможно, вам, скорее всего, понадобится Semaphore —, а именно коллекция семафоров, по одной для каждой группы цветов.