当前位置: 首页 > 知识库问答 >
问题:

Java信号量,acquire()和release()

益承颜
2023-03-14

我是java的初学者,我正在试验信号量。我试图编写一个包含writer和reader的代码,我只尝试使用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();

      }
   }


} 

共有1个答案

相野
2023-03-14

对于使用信号量的读写器问题,您可以遵循以下解决方案。它处理所有提到的条件并使用java。util。同时发生的信号量实现信号量的包。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();
         }
      }
   }

所有类都已包含在解决方案中。希望有帮助!

 类似资料:
  • 我有一些线程,它们被赋予随机数(1到n),并被指示按排序顺序打印它们。我使用了信号量,这样我就获得了许可数=随机数,并释放了一个比所获得的多的许可。 获得=随机数;释放=1个随机数 信号量的初始许可计数为1。所以随机数为1的线程应该获得许可,然后是2,依此类推。 这是根据下面给出的文档支持的 不要求释放许可证的线程必须通过调用acquire()获得该许可证。 问题是我的程序在1代表n后卡住了 我的

  • 我试图理解这个旧考试任务的答案,在这个任务中,学生应该使用JavasReentrantLock实现一个公平的二进制信号量。我不明白这些计数器的意义: 它在任务的描述中说,“你可以假设程序中使用信号量最多有20个线程。此外,最多1000万信号量操作将在程序的一次运行中执行。"在任务的解决方案中,它说:“每个试图获取信号量的线程必须在队列中注册自己,并且只有在之前的线程离开队列后才离开队列。每个线程使

  • 首先想到的问题是,为什么我们需要信号量? 一个简单的答案,以保护多个进程共享的关键/共同区域。 假设多个进程正在使用相同的代码区域,如果所有人都想并行访问,那么结果是重叠的。 例如,多个用户仅使用一台打印机(通用/关键部分),例如个用户,同时给予个作业,如果所有作业并行启动,则一个用户输出与另一个用户输出重叠。 因此,我们需要使用信号量来保护这个信号,即当一个进程正在运行时锁定关键部分,并在完成时

  • 信号量 信号量是一种同步互斥机制的实现,普遍存在于现在的各种操作系统内核里。相对于spinlock 的应用对象,信号量的应用对象是在临界区中运行的时间较长的进程。等待信号量的进程需要睡眠来减少占用 CPU 的开销。参考教科书“Operating Systems Internals and Design Principles”第五章“同步互斥”中对信号量实现的原理性描述: struct semaph

  • 一个线程发送信号量,另外一个线程接收信号量 一个线程发送信号量,另外一个线程接收信号量 源码/* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2018-08-24 yangjie

  • 信号量接口 结构体 struct   rt_semaphore   信号量控制块 更多...   类型定义 typedef struct rt_semaphore *  rt_sem_t   信号量类型指针定义   函数 rt_err_t  rt_sem_init (rt_sem_t sem, const char *name, rt_uint32_t value, rt_uint8_t flag