首页 > 解决方案 > Java 信号量,acquire() 和 release()

问题描述

我是 java 的初学者,我正在尝试使用 Semaphore。我试图编写一个有作者和读者的代码,我只尝试使用acquire()和release():

1)如果一个作家正在写作,那么同时没有其他作家可以写作,也没有读者可以阅读。
2)多个阅读器可以同时阅读,但如果至少有一个活动阅读器,那么作者就不能写任何东西。

因此,总而言之,可以有
- 一个阅读器,没有作者
- 多个阅读器,没有作者
- 一个作者,没有阅读器

我尝试编写下面的代码,我知道它可能非常糟糕,但我真的很难理解这个概念并且代码不起作用,我不知道如何修复它。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class Main 
{


    public static void main(String [] args) 
    {
        ExecutorService executorService = Executors.newCachedThreadPool();
        ReadWriteLock RW = new ReadWriteLock();

        executorService.execute(new Writer(RW));
        executorService.execute(new Writer(RW));
        executorService.execute(new Writer(RW));
        executorService.execute(new Writer(RW));

        executorService.execute(new Reader(RW));
        executorService.execute(new Reader(RW));
        executorService.execute(new Reader(RW));
        executorService.execute(new Reader(RW));                
    }
}


class ReadWriteLock
{


    private int reader = 0;
    private Semaphore write = new Semaphore(1);

    public void readLock()  
    {           
        if (write.availablePermits() == 1)
        {
            reader++;
        }
    }

    public void writeLock() 
    {       
        if (write.availablePermits() == 1)
        {
            try 
            {
                write.acquire();
            } 
            catch(InterruptedException e)
            {
                e.printStackTrace();;
            }
        }

    }

    public void readUnLock() 
    {
         if (reader > 0)
            reader--;
    }

    public void writeUnLock() 
    {

        if (write.availablePermits() == 0)
        {
            write.release();
        }

    }

}




class Writer implements Runnable
{
   private ReadWriteLock RW_lock;


    public Writer(ReadWriteLock rw) {
        RW_lock = rw;
   }

    public void run() {
      while (true){
          RW_lock.writeLock();

          RW_lock.writeUnLock();

      }
   }


}



class Reader implements Runnable
{
   private ReadWriteLock RW_lock;


   public Reader(ReadWriteLock rw) {
        RW_lock = rw;
   }
    public void run() {
      while (true){               
          RW_lock.readLock();


          RW_lock.readUnLock();

      }
   }


} 

标签: javasemaphore

解决方案


您可以使用信号量按照以下解决方案来解决读写器问题。它处理所有提到的条件并使用java.util.concurrent.Semaphore包来实现信号量。 http://www2.hawaii.edu/~walbritt/ics240/synchronization/ReaderWriterSolution.java

您必须在读取器和写入器上定义锁。以下是所有读卡器锁的接口。

interface RWLock{
       public abstract void acquireReadLock(int readerNum);
       public abstract void acquireWriteLock(int writerNum);
       public abstract void releaseReadLock(int readerNum);
       public abstract void releaseWriteLock(int writerNum);
   }

Database.java包含所有读写函数的定义:

class Database implements RWLock{
      private int readerCount;  // the number of active readers
      private Semaphore mutex;  // controls access to readerCount
      private Semaphore db;     // controls access to the database

       public Database() {
         readerCount = 0;
         mutex = new Semaphore(1);
         db = new Semaphore(1);
      }

       public void acquireReadLock(int readerNum) {
         try{
         //mutual exclusion for readerCount 
            mutex.acquire();
         }
             catch (InterruptedException e) {}

         ++readerCount;

      // if I am the first reader tell all others
      // that the database is being read
         if (readerCount == 1){
            try{
               db.acquire();
            }
                catch (InterruptedException e) {}
         }

         System.out.println("Reader " + readerNum + " is reading. Reader count = " + readerCount);
         //mutual exclusion for readerCount
         mutex.release();
      }

       public void releaseReadLock(int readerNum) {
         try{
         //mutual exclusion for readerCount
            mutex.acquire();
         }
             catch (InterruptedException e) {}

         --readerCount;

      // if I am the last reader tell all others
      // that the database is no longer being read
         if (readerCount == 0){
            db.release();
         }

         System.out.println("Reader " + readerNum + " is done reading. Reader count = " + readerCount);

      //mutual exclusion for readerCount
         mutex.release();
      }

       public void acquireWriteLock(int writerNum) {
         try{
            db.acquire();
         }
             catch (InterruptedException e) {}
         System.out.println("Writer " + writerNum + " is writing.");
      }

       public void releaseWriteLock(int writerNum) {
         System.out.println("Writer " + writerNum + " is done writing.");
         db.release();
      }


   }

现在您将需要分别实现读取器和写入器。通过获取锁并遵循上述条件:

  • 一个读者,没有作家
  • 多个读者,没有作者
  • 一个作家没有读者
class Reader implements Runnable
   {

      private RWLock database;
      private int readerNum;

       public Reader(int readerNum, RWLock database) {
         this.readerNum = readerNum;
         this.database = database;
      }

       public void run() {
         while (true) {
            SleepUtilities.nap();

            System.out.println("reader " + readerNum + " wants to read.");
            database.acquireReadLock(readerNum);

         // you have access to read from the database
         // let's read for awhile .....
            SleepUtilities.nap();

            database.releaseReadLock(readerNum);
         }
      }
   ;
   }

   class Writer implements Runnable
   {
      private RWLock database;
      private int writerNum;

       public Writer(int w, RWLock d) {
         writerNum = w;
         database = d;
      }

       public void run() {
         while (true){
            SleepUtilities.nap();

            System.out.println("writer " + writerNum + " wants to write.");
            database.acquireWriteLock(writerNum);

         // you have access to write to the database
         // write for awhile ...
            SleepUtilities.nap();

            database.releaseWriteLock(writerNum);
         }
      }


   }

最后你需要一个运行类来测试解决方案

import java.util.concurrent.Semaphore;

    public class ReaderWriterSolution{
      public static final int NUM_OF_READERS = 3;
      public static final int NUM_OF_WRITERS = 2;

       public static void main(String args[]){
         RWLock database = new Database();

         Thread[] readerArray = new Thread[NUM_OF_READERS];
         Thread[] writerArray = new Thread[NUM_OF_WRITERS];

         for (int i = 0; i < NUM_OF_READERS; i++) {
            readerArray[i] = new Thread(new Reader(i, database));
            readerArray[i].start();
         }

         for (int i = 0; i < NUM_OF_WRITERS; i++) {
            writerArray[i] = new Thread(new Writer(i, database));
            writerArray[i].start();
         }
      }
   }

所有的类都包含在解决方案中。希望能帮助到你!


推荐阅读