2

这是reader writer 的一种实现,即很多reader 可以读,但在任何时候只有一个writer 可以写。这是否按预期工作?

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

4 回答 4

6

不-您隐式调用this.wait(),尽管没有同步 on this,而是在课堂上。同样,您正在调用this.notifyAll(). read_end我的建议:

  • 不要扩展Thread- 你根本没有专门研究线程。
  • 不要在实例成员中使用这样的静态变量;它使每个对象看起来都有状态,但实际上没有。就我个人而言,我只会使用实例变量。
  • 不要在名称中使用下划线 - 传统的 Java 名称将是numReaders, readEnd(或更好的endRead)等。
  • this如果可以帮助,请不要在任何一个或类上同步。就个人而言,我更喜欢有一个private final Object变量来锁定(并等待等)。这样你就知道只有你的代码可以在上面同步,这使得推理更容易。
  • 您从未设置writing为 0。首先使用整数而不是 a 的任何原因boolean

当然,如果可能的话,最好使用框架中的类——但我希望你写这篇文章是为了更好地理解线程。

于 2011-05-22T18:35:06.623 回答
3

您可以通过使用更简单的方式实现您的目标

java.util.concurrent.locks.ReentrantReadWriteLock

开始阅读时抓住 java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock ,开始写作时抓住 java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock 。

这个类正是为此而设计的——允许多个阅读器与单个作者互斥。

于 2011-05-22T18:42:58.837 回答
2

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

顺便说一句,有一个读/写锁的实现,它随核心 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();
}

和类似的写操作。

于 2011-05-22T18:40:57.497 回答
0

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

于 2011-05-22T18:59:03.573 回答