2013-06-21 6 views
0

Я хочу иметь объект с методом, который только печатает числа, которые еще не были получены, поэтому я использовал следующий код. Идея состоит в том, что я использую карту, которая для каждого целого хранит блокировку, поток ожидает блокировку, если она уже находится на карте, иначе она поместит новую блокировку в карту с этим целым как ключ и объект Integer как значение,Отключить блокировку карты и блокировать захват значения

Примечание: Я использую Integer(a) как замок для целого a

проблема заключается в том, что я хочу снять блокировку карты, и я хочу ждать на замке, который извлекается из карты, но race condition происходит, любая идея для решения проблемы?

public class sync_print { 
    public static void main(String[] args) { 
     sync_print syobj = new sync_print(); 
     Thread t1 = new Thread(new worker(syobj, 10) , "thread 1"); 
     Thread t2 = new Thread(new worker(syobj, 10) , "thread 2"); 
     Thread t3 = new Thread(new worker(syobj, 4) , "thread 3"); 
     Thread t4 = new Thread(new worker(syobj, 5) , "thread 4"); 
     Thread t5 = new Thread(new worker(syobj, 5) , "thread 5"); 
     t1.start(); 
     t2.start(); 
     t3.start(); 
     t4.start(); 
     t5.start(); 
    } 


    HashMap<Integer, Integer> lock_map = new HashMap<Integer , Integer>(); 
    void print(int a) throws InterruptedException{ 
     synchronized(lock_map){ 
      Integer lock = lock_map.get(a); 
      if (lock != null){ 
       synchronized (lock) { 
        System.out.println(Thread.currentThread().getName() + " is waiting"); 
        lock_map.notify(); 
        lock.wait(); 
       } 
      }else{ 
       lock_map.put(a, new Integer(a)); 
       System.out.println(a); 
      } 
     } 
    } 
} 

class worker implements Runnable{ 
    int val; 
    sync_print obj; 
    public worker(sync_print obj , int v){ 
     this.val = v; 
     this.obj = obj; 
    } 
    public void run() { 
     try { 
      obj.print(val); 
     } catch (InterruptedException e) {} 
    } 
} 

ответ

0

Вы можете быть в состоянии устранить блокировку lock_map путем замены вашего HashMap с ConcurrentHashMap. Изменить lock_map.put на lock_map.putIfAbsent.

+0

Я не понимаю, как это связано с проблемой, можете ли вы подробно рассказать? –

+0

@Arian Hosseinzadeh Я не совсем понимаю, что делает ваша блокировка на 'lock_map', но если это так, чтобы предотвратить одновременное одновременное вызов нескольких вызовов из' lock_map.put', вы можете использовать 'ConcurrentHashMap # putIfAbsent' для выполните это вместо этого - если два потока вызовут 'putIfAbsent' в то же время, то только один будет успешным. –

0

Ваш wait не находится внутри цикла. См. elsewhere, почему это может создать проблемы.