简体   繁体   English

Java优化的读/写共享资源/内存位置,无需Atomic API,例如AtomicInteger

[英]Java optimized read/write a shared resource/memory location without Atomic API e.g. AtomicInteger

There is a shared resource and we need to perform read/write operations on it as per below: 有一个共享资源,我们需要按照以下步骤对其执行读/写操作:

  1. When a write on resource is going on then no read should be allowed. 当正在进行资源写操作时,则不允许读取。
  2. When a read is going on then no write should be allowed but multiple read threads should be able to read. 当正在进行读取时,则不允许写入,但应能够读取多个读取线程。

I have written code like mentioned below but the problem with this code is all reads will be blocked when a single read thread has acquired the lock. 我已经编写了如下所述的代码,但是此代码的问题是,当单个读取线程获得了锁时,所有读取都会被阻止。 Further i am thinking to use a boolean flag eg canReadContinue. 此外,我正在考虑使用布尔标志,例如canReadContinue。 Now the first time when read acquires a lock i will flip this flag to true and if it is true then other threads should not try to acquire the lock. 现在,当read第一次获得锁时,我会将此标志翻转为true,如果为true,则其他线程不应尝试获取该锁。

class SharedResource {

    Lock writeLock

    public Object read() {
        writeLock.acquire()
        doRead()

    }

    public void write(Object toBeWritten) {
        writeLock.acquire()

        doWrite(toBeWritten)

        writeLock.release()
    }

}

Expected is multiple threads should be able to read when no write is going on. 预期没有写操作时多个线程应该能够读取。

UPDATED 1 : 更新1:

public class SharedResource { 公共类SharedResource {

private Object writeLock = new Object();
private volatile boolean canReadContinue;
private volatile int readCount;

public void write(Object newState) throws InterruptedException {
    synchronized (writeLock) {
        // To make sure no read is going on
        while (readCount > 0) {
            wait();
        }
        System.out.println("Write thread has the lock.");
        doWrite(newState);
    }
}

public Object read() {
    if(canReadContinue) {
        incrementCount();
    } else {
        synchronized (writeLock) {
            System.out.println("Read thread has the lock.");
            canReadContinue = true;
            incrementCount();
        }
    }
    Object result = doRead();
    decrementCount();
    if(readCount == 0) {
        // TODO - release lock and notify

    }

    return result;
}

private synchronized void incrementCount() {
    readCount++;
}

private synchronized void decrementCount() {
    readCount--;
}


private void doWrite(Object newState) {
    // do stuff
}

private Object doRead() {
    return "";
}

} }

Now i need a mechanism to release the lock at line "// TODO - release lock and notify", any pointers how to resolve this issue ? 现在,我需要一种在“ // TODO-释放锁并通知”行中释放锁的机制,任何指针如何解决此问题?

Hints: 提示:

  • You need a mutex; 您需要一个互斥锁; eg a primitive object lock. 例如原始对象锁。
  • You need a counter of the number of readers currently holding a logical read lock. 您需要一个计数器,该计数器包含当前持有逻辑读取锁的读取器的数量。
  • You need a flag to say if a writer is holding a logical write lock. 您需要一个标志来说明写程序是否持有逻辑写锁。
  • You hold the mutex if and only you are acquiring or releasing a logical lock. 仅当您正在获取或释放逻辑锁时,才持有互斥量。 Once you have acquired it, you release the mutex. 一旦获得它,就释放互斥量。
  • You will need to use wait and notify . 您将需要使用waitnotify

Effectively you need to 1 implement a simplified version ReadWriteLock . 有效地,您需要1实现简化版本ReadWriteLock


1 - ... for the purposes of your homework assignment. 1-...用于您的家庭作业。 In a real world program, you should simply use the existing ReadWriteLock class. 在实际程序中,您应该仅使用现有的ReadWriteLock类。

Further i am thinking to use a boolean flag eg canReadContinue 此外,我正在考虑使用布尔标志,例如canReadContinue

You're on the right track. 您走在正确的轨道上。 But remember that any number of threads could concurrently perform their read accesses and that the write access can only be done if no other thread is currently reading or writing. 但是请记住, 任何数量的线程都可以同时执行其读取访问,并且仅当当前没有其他线程正在读取或写入时,才可以执行写入访问。

So you need to keep track of how many readers are currently holding the lock, and every reader must make sure to release the lock when it's done. 因此,您需要跟踪当前有多少个读取器持有该锁,并且每个读取器必须确保在完成锁后将其释放。 Only if & when 0 readers (and 0 writers) hold the lock, a writer may proceed; 仅当&当0个读者(和0个作者)持有锁时,作者才可以继续操作; and only if & when 0 writers hold the lock, any reader may proceed. 并且仅当&时有0个作者持有锁,并且任何读者都可以继续。

Answering on your updated code here is some skeleton for you to complete: 在这里回答更新后的代码是您需要完成的一些基本工作:

public class SharedResource {

  private final Object signal = new Object();
  private boolean writeLocked;
  private int readerCount;

  public void write(final Object newState) throws InterruptedException {

    this.acquireWriteLock();

    try {

      // Now we know that no read and no other write is going on.
      System.out.println("Write thread has the lock.");
      this.doWrite(newState);

    } finally {
      // make sure we release the lock in any case.
      this.realeaseWriteLock();
    }

  }

  private void acquireWriteLock() throws InterruptedException {
    synchronized (this.signal) {

      // Wait until no more readers *and* no writer holds the lock.

      // To do: Insert the condition we need to wait for:

      while (/* condition here! */ ) {
        // To do: Wait for the lock-holding thread(s) to signal that they released their lock(s).
      }

      this.writeLocked = true; // Let others know that the write lock has been taken.

    }
  }

  private void realeaseWriteLock() {
    synchronized (this.signal) {

      this.writeLocked = false;

      // To do: Notify any and all other waiting threads that we released the lock!

    }
  }

  public Object read() {

    // To be done...

  }

  private void acquireReadLock() throws InterruptedException {
    synchronized (this.signal) {

      // Wait until no *writer* holds the lock.
      // To do: Insert condition we need to wait for:

      while (/* condition here! */ ) {
         // To do: Wait for the lock-holding thread(s) to signal that they released their lock(s).

      }

      // Now we know that no writer holds the lock. Acquire (another) read lock:

      this.readerCount++;

    }
  }

  private void releaseReadLock() throws InterruptedException {
    synchronized (this.signal) {

      this.readerCount--;

      // To do: Notify any threads waiting (i.e. writer threads).

      // (In fact only *required* if there are *no* more readers now because that's the only condition any thread will wait on.)

    }
  }

  private void doWrite(final Object newState) {
    // do stuff
  }

  private Object doRead() {
    return "";
  }

}

The main point to understand may be that every attempt to take a lock may have to wait , and that every release of a lock should notify any (potential) waiting threads. 要理解的主要点可能是, 每次尝试获取锁的尝试都可能必须wait ,并且每次释放锁都应notify任何(潜在的)等待线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在 Java 中,每个共享引用是否占用另一个内存字(例如 32 位或 64 位)? - Does each shared reference take up another word of memory (e.g. 32 or 64 bits) in Java? 资源节省内存上的Java读写锁 - Java Read Write Locks on a resource conserving memory 如何在Java中映射(mmap)linux块设备(例如/ dev / sdb)? - How to memory map (mmap) a linux block device (e.g. /dev/sdb) in Java? Java - 将一个文件中的内容逐块(例如 8 字节)交替写入多个文件 - Java - Write content from one file chunk by chunk (e.g. 8 Bytes) alternately into multiple files AtomicInteger原子 - AtomicInteger atomic 如何在 Java 中阅读完整的堆栈跟踪,例如“……还有 23 个” - How to read the full stacktrace in Java where it says e.g. “… 23 more” 从外部数据源修改 Java JTable AbstractTableModel(例如从套接字读取的数据) - Modify Java JTable AbstractTableModel from external data source (e.g. data read from a socket) 是AtomicInteger的嵌套方法调用在Java中也是原子的 - Are nested method calls of AtomicInteger also atomic in java 如何在没有任何动画(例如淡入淡出)的情况​​下显示/隐藏软键盘? - How to show/hide the soft keyboard without any animation (e.g. fade) in Java? 是什么的J字头和没有如-J-XMS和-Xmx通过java选项之间的区别? - What is the difference between java option passed with J prefix and without e.g. -J-Xms and -Xmx?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM