2

我是在 java 中使用线程的新手。我有一个简单的读写器问题,当作者进入线程时,读者将等待作者完成。

但是,当我运行我的程序时,我发现我的线程没有得到通知?为什么是这样?

我的代码如下:

public class ReaderWriter  {

Object o = new Object();
volatile boolean writing;
Thread readerThread = new Thread( "reader") {

    public void run() {

        while(true) {
            System.out.println("reader starts");
            if(writing) {
            synchronized (o) {
                try {
                    o.wait();
                    System.out.println("Awaked from wait");
                } catch (InterruptedException e) {                      
                    e.printStackTrace();
                }

            }
        }

            System.out.println( "reader thread working "+o.hashCode());

        }

    }
};
Thread writerThread = new Thread("writer" ) {
    public void run() {
        System.out.println( " writer thread");
        try {
            synchronized (o) {
                writing = true;
                System.out.println("writer is working ..  ");
                Thread.sleep(10000);                    
                writing = false;
                o.notify();
                System.out.println("reader is notified");
            }


        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
};

public static void main(String[] args) {
    ReaderWriter rw=new ReaderWriter();
    rw.readerThread.start();

    rw.writerThread.start();

}

}

4

5 回答 5

4

这里的问题在于synchronized (o)功能。

synchronized 函数使线程同步,因此它一次只对对象执行一个线程o。因此,虽然 的值为writing真。由于 在readerThread_synchronized (o)readerThread

你得到一个无限循环,因为没有终止语句。
这里知道线程何时终止

查看此代码以了解有关同步功能的更多信息

synchronized(object) {
   // statements to be synchronized
}

这里,object 是对正在同步的对象的引用。同步块确保只有在当前线程成功进入对象的监视器后才会调用对象成员的方法

.

阅读本文以检查通知方法

JavaSW 中的 Object 类具有三个 final 方法,它们允许线程就资源的锁定状态进行通信。这些方法是wait()、notify() 和 notifyAll()。线程通过具有该资源实例的同步块获得特定资源的锁。假设一个线程要求另一个线程在对资源进行操作之前对资源执行某种操作。该线程可以在资源上同步并在资源上调用 wait() 方法。这表示线程将等待,直到它被通知它可以继续执行。

wait() 方法可以将可选的超时值作为参数。如果使用此值,则意味着线程将等待直到收到通知,或者一旦超时值过去,它将继续执行。

如果一个线程需要在另一个线程对资源进行操作之前对资源执行任务(并且另一个线程正在通过wait()资源上的方法等待),则该线程需要在资源上进行同步。它可以对资源执行其操作。

为了在这些操作完成后通知等待线程,notify()调用资源上的方法。这通知等待线程它可以继续执行操作。如果多个线程正在等待资源,则无法保证哪个线程将被授予对资源的访问权限。如果希望唤醒所有等待的线程,则notifyAll()可以在资源上调用该方法。

于 2013-08-26T14:29:31.613 回答
1

问题是writing设置为错误的事先通知。

Thread.sleep()单独不会唤醒其他等待线程。

于 2013-08-26T14:11:42.487 回答
1

设置writingtrue. _ 这就是为什么当writing设置为true.

synchronized (o) { // Thread aquires lock on monitor o. writing is false.
    writing = true; // writing is true, lock still held.
    System.out.println("Writer is working...");
    Thread.sleep(1000); // Thread sleeps while holding lock.
    writing = false; // writing is changed back to false, lock still held.
    o.notify();
    System.out.println("Reader is notified");
} // Here lock is released, writing is false.

这是在获取锁之前writing设置false的,并且是false在释放锁时设置的。当锁被持有时,读者线程中的这个同步块将不会被输入:

while (true) {
    if (writing) {
        synchronized (o) { // Lock always held by writer when writing=true.
            try {
                o.wait();
                System.out.println("Awaked from wait");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
于 2013-08-26T14:59:08.887 回答
0

感谢您的合作和宝贵的建议,我对我的代码进行了一些更改

public class ReaderWriter  {

Object o = new Object();
volatile boolean writing;
Thread readerThread = new Thread( "reader")  {

    public void run() {
        System.out.println("reader starts");

            synchronized (o) {
                    System.out.println("reader aquire the lock");
                    while(writing) {
                        try {                               
                            System.out.println("Reader goes to wait ....");
                            o.wait();                               
                            System.out.println("Awaked from wait");
                        } catch (InterruptedException e) {                      
                            e.printStackTrace();
                        }
                    }
                    while(!writing) {
                        //do something  
                        System.out.println("hiiiiiiii");
                    }
                    System.out.println("reader release the lock");  
                }
        }

    };

Thread writerThread = new Thread("writer" ) {
    public void run() {
        System.out.println( "writer starts");
        try {
            writing = true;
            synchronized (o) {                  
                System.out.println("writer aquire the lock");
                Thread.sleep(10000);        
                o.notify();                 
                System.out.println("reader is notified");
                System.out.println("writer release the lock");
            }
            writing = false;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
};

public static void main(String[] args) {
    ReaderWriter rw=new ReaderWriter();
    rw.readerThread.start();        
    rw.writerThread.start();

}

}

现在我发现了一件非常有趣的事情,即“等待等待”仅当读者首先获得锁并且在更正之后我将 write = true 和 writing = false 放在同步块之外,以便在读者获得锁后当 writer 到来它更改写入标志,因此读取器等待并释放写入器的锁,写入器获取锁执行 Thread.sleep 并通知读取器,从而释放读取器的锁。Reader 醒来,发现 writer 将写入标志设置为 false,因此 reader 开始执行其操作。

于 2013-08-26T17:14:34.880 回答
0
There can be only two cases when writer thread first enters its critical section or when reader thread enters first since by no means you are stopping one to sleep for other to start first.

1) In first case when writer thread enters critical section first synchronized block locks the object o and after waking up from sleep you notify but you are not releasing lock explicitly till sync block ends which unlocks the object automatically .So even if notification is sent inside block reader thread wont be able to take the lock .So after syn block of your writer thread is over you reader thread would run uninterrupted assuming there is no interrupt from third thread .

2) In second case when  you reader thread is scheduled by scheduler to run first it will obtain a lock and on finding flag false it will enter infinite loop of printing hi on output console and its is infinite since you have take lock of object and entered infinite loop which makes writer thread wait indefinitely on reader thread  

Correcting your code as below for reader thread 

synchronized (o) {
    System.out.println("reader aquire the lock");
    if(writing) {
        try {                               
            System.out.println("Reader goes to wait ....");
                            System.out.println("Awaked from wait");
        } catch (InterruptedException e) {                      
            e.printStackTrace();
        }
    }
    else{
        //do something 
        o.notify(); 
        o.wait(); // in this case only reader release the lock would only be printed and if block wont be executed
    }
    System.out.printn("reader release the lock");  
}
于 2016-12-21T16:41:40.410 回答