2016-11-22 5 views
-1

Я пытаюсь создать базовую реализацию Semaphore с использованием Queue. Идея в том, что есть база данных, и есть 10 авторов. Писатели могут писать только в базу данных во взаимном исключении. Я использую Queue, потому что хочу реализовать First In First Out и Last In First Out.Реализация семафора с очередью

Используя Семафор, я не могу уведомить конкретный поток, чтобы проснуться. Поэтому моя идея заключается в том, что я делаю для каждого Writer, я создаю объект и говорю Writer ждать этого объекта. Помещает этот объект в очередь. Затем удалите объект из очереди и сообщите об этом Thread, ожидающем этого объекта. Таким образом, я думаю, что могу сделать реализацию FIFO или LIFO.

Мне нужна помощь по реализации фактического кода: 1. Я запускаю код ниже, он дал мне много IllegalMonitorStateException. 2. Код FIFO и LIFO (мой код FIFO кажется неправильным, а для кода LIFO я думаю использовать Stack вместо Queue).

public class Test { 
    public static void main(String [] args) { 
    Database db = new Database(); 

    for (int i = 0; i < 10; i++) 
     (new Thread(new Writer(db))).start(); 
    } 
} 

public class Writer implements Runnable { 

    private Database database; 

    public Writer(Database database) { 
    this.database = database; 
    } 

    public void run() { 
    this.database.acquireWriteLock(); 

    this.database.write(); 

    this.database.releaseWriteLock(); 
    } 
} 

public class Database { 

    private Semaphore lockQueue; 

    public Database() { 
    this.lockQueue = new Semaphore(); 
    } 

    public void write() { 
    try { 
     Thread.sleep(1000); 
    } catch (InterruptedException ie) {} 
    } 

    public void acquireWriteLock() { 
    lockQueue.acquire(); 
    } 

    public void releaseWriteLock() { 
    lockQueue.release(); 
    } 
} 

import java.util.Queue; 
import java.util.LinkedList; 

public class Semaphore { 
    private Queue<Object> queue; 

    public Semaphore() { 
    this.queue = new LinkedList<Object>(); 
    } 

    public synchronized void acquire() { 
    Object object = new Object(); 

    try { 
     if (this.queue.size() > 0) { 
     object.wait(); 
     this.queue.add(object); 
     } 
    } catch (InterruptedException ie) {} 

    this.queue.add(object); 
    } 

    public synchronized void release() { 
    Object object = this.queue.remove(); 
    object.notify(); 
    } 
} 

ответ

1

Вам необходимо приобрести блокировку объекта, прежде чем вы сможете использовать wait() и notify(). Попробуйте проверить, если следующий код будет работать:

public class Semaphore { 
    private Queue<Object> queue; 
    private int state; 

    public Semaphore() { 
     this.queue = new LinkedList<Object>(); 
    } 

    public void acquire() { 
     Object object = new Object(); 

     synchronized (object) { 
      try { 
       if (this.state > 0) { 
        this.queue.add(object); 
        object.wait();     
       } else { 
        state++; 
       } 

      } catch (InterruptedException ie) { 
      } 

     } 
    } 

    public void release() { 
     Object object = this.queue.poll(); 

     state--; 

     if(null == object) { 
      return; 
     } 

     synchronized (object) { 
      object.notify(); 
     } 
    } 
} 
+0

В чем разница между этим кодом и тот, который я написал выше? Я использую 'object.wait()' вместо 'wait()', потому что я хочу ждать этого объекта, поэтому я могу использовать его как очередь. Если я просто использую 'wait()', не означает ли это, что я жду этого экземпляра Semaphore, и когда я делаю 'notify()', я не могу сообщить об определенном потоке, чтобы проснуться. –

+0

Я редактировал код основанный на следующих причинах: 1st, IllegalMonitorStateException выбрасывается, поскольку экземпляр Semaphore заблокирован вместо экземпляра объекта. 2, вместо размера очереди используется целое число, определяющее, есть ли рабочие потоки. Если размер Queue используется, и объект добавлен, поток может удалить один и тот же объект, что приведет к взаимоблокировке. –

+0

Спасибо, это именно то, что мне нужно. Можете ли вы подробнее рассказать о том, почему это синхронизированный блок при приобретении и выпуске вместо синхронизированных методов. –

Смежные вопросы