读者编写问题并发Java

时间:2011-05-22 18:30:44

标签: java concurrency readerwriterlock

这是读者作者的一种实现,即许多读者可以阅读,但任何时候只有一个作家可以写。这是否按预期工作?

public class ReadersWriters extends Thread{

static int num_readers = 0;
static int writing = 0;

public void read_start() throws InterruptedException {         

    synchronized(this.getClass()) {
        while(writing == 1) wait();
        num_readers++;
    }        
}

public void read_end() {
    synchronized(this.getClass()) {
        if(--num_readers == 0) notifyAll();
    }
}

public void write_start() throws InterruptedException{

    synchronized(this.getClass()) {
        while(num_readers > 0) wait();
        writing = 1;
    } 
}

public void write_end() {
    this.getClass().notifyAll();
}
}

此实现也与声明每个方法

有任何不同
public static synchronized read_start() 

例如?

由于

4 个答案:

答案 0 :(得分:6)

不 - 你隐含地调用this.wait(),尽管没有在this上同步,而是在课堂上。同样,您在this.notifyAll()中呼叫read_end。我的建议:

  • 不要延长Thread - 你根本不专门研究这个主题。
  • 不要使用来自实例成员的静态变量;它使看起来就像每个对象的状态一样,但实际上并没有。我个人只是使​​用实例变量。
  • 不要在名称中使用下划线 - 传统的Java名称为numReadersreadEnd(或更好,endRead)等。
  • 如果可以提供帮助,请同步。就个人而言,我更喜欢使用this变量来锁定(并等待等)。这样你就知道只有你的代码可以在它上面进行同步,这样可以更容易推理。
  • 您从未将private final Object设置为0.首先使用整数而不是writing的原因是什么?

当然,如果可能的话,最好在框架中使用这个类 - 但我希望你真的写这篇文章来更好地理解线程。

答案 1 :(得分:3)

您可以使用

以更简单的方式实现目标
java.util.concurrent.locks.ReentrantReadWriteLock

开始阅读时,只需抓取java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock,开始编写时抓住java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock。

此类正是为此目的 - 允许多个与单个编写器互斥的读者。

答案 2 :(得分:2)

read_start的特定实现并不等同于简单地声明方法synchronized。正如J. Skeed所指出的那样,您需要在notify对象上调用wait(和synchronize)。您不能使用不相关的对象(此处为:类)。使用方法上修改的synchronized不会使方法隐式调用wait或类似的东西。

BTW。是一个读/写锁的实现,它随核心JDK一起提供:java.util.concurrent.locks.ReentrantReadWriteLock。使用该代码,您的代码可能如下所示:

class Resource {
    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    private final Lock rlock = lock.readLock();
    private final Lock wlock = lock.writeLock();

    void read() { ... /* caller has to hold the read lock */ ... }
    void write() { ... /* caller has to hold the write lock */ ... }

    Lock readLock() { return rlock; }
    Lock writeLock() { return wlock; }
}

用法

final Resource r = ...;

r.readLock().lock();
try {
    r.read();
} finally {
    r.unlock();
}

和写操作类似。

答案 3 :(得分:0)

示例代码在this.getClass()上同步,它将在同一个类加载器中为Class的多个实例返回相同的ReadersWriters对象。如果存在ReadersWriters的多个实例,即使您有多个线程,也会存在对此共享锁的争用。这类似于将static关键字添加到私有锁定字段(如Jon Skeet建议的那样),并且可能导致比在this或私有锁定对象上同步更差的性能。更具体地说,正在读取的一个线程将阻止正在写入的另一个线程,这可能是不合需要的。