2011-07-10 14 views
2

LinkedListは、データをポーリングするときに例外をスローします。しかし、私は正しく読み取り/書き込みロックの概念を使用すると思います。そのコードの何が間違っていますか?なぜこのReadWriteLockの例はうまくいかないのですか?

package sample; 

import java.util.ArrayList; 
import java.util.LinkedList; 
import java.util.List; 
import java.util.Queue; 
import java.util.concurrent.ArrayBlockingQueue; 
import java.util.concurrent.ConcurrentLinkedQueue; 
import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReadWriteLock; 
import java.util.concurrent.locks.ReentrantReadWriteLock; 


public class PingPong extends Thread { 
    boolean read = false; 
    Queue<String> queue; 
    static ReadWriteLock lock = new ReentrantReadWriteLock(); 
    final static Lock readLock = lock.readLock(); 
    final static Lock writeLock = lock.writeLock(); 
    boolean stop; 

    public PingPong(boolean read, Queue<String> queue) { 
     this.read = read; 
     this.queue = queue; 
    } 

    int count = 0; 

    @Override 
    public String toString() { 
     return "PingPong{" + 
       "read=" + read + 
       ", count=" + count + 
       '}'; 
    } 

    @Override 
    public void run() { 
     if (read) { 
      while (!stop) { 

       readLock.lock(); 
//    synchronized (queue) { 
       try { 

        String string = queue.poll(); 
        if (string != null) { 
         count++; 
        } 
       } finally { 
        readLock.unlock(); 
       } 


//    } 
       inform(); 
      } 
     } else { 
      while (!stop) { 

       writeLock.lock(); 
//    synchronized (queue) { 
       try { 
        if (queue.add("some str" + count)) { 
         count++; 
        } 
       } finally { 
        writeLock.unlock(); 
       } 

//    } 

       inform(); 
      } 

     } 


    } 

    private void inform() { 
//  Thread.yield(); 
//  synchronized (queue) { 
//   queue.notify(); 
//   try { 
//    queue.wait(1); 
//   } catch (InterruptedException e) { 
//    e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. 
//   } 
//  } 
    } 

    public static void main(String[] args) throws InterruptedException { 
     Queue<String> queue = new LinkedList(); 
//  queue = new ArrayBlockingQueue<String>(100); 
//  queue = new ConcurrentLinkedQueue<String>(); 
     List<PingPong> pongs = new ArrayList<PingPong>(); 
     for (int i = 0; i < 10; ++i) { 
      PingPong pingPong = new PingPong(i % 2 == 0, queue); 
      pingPong.start(); 
      pongs.add(pingPong); 
     } 
     Thread.sleep(1000); 
     int sum = 0; 
     int read = 0; 
     int write = 0; 
     for (PingPong pp : pongs) { 
      pp.stop = true; 
      pp.join(); 
     } 
     for (PingPong pp : pongs) { 
      System.out.println(pp); 
      sum += pp.count; 
      if (pp.read) read += pp.count; 
      else write += pp.count; 
     } 
     System.out.println(sum); 
     System.out.println("write = " + write); 
     System.out.println("read = " + read); 
     System.out.println("queue.size() = " + queue.size()); 
     System.out.println("balance (must be zero) = " + (write - read - queue.size())); 

    } 
} 
+1

例外はありますか? – vcsjones

+0

質問を投稿する前に、例外を貼り付けてコードを整理してください。ありがとうございました。 –

答えて

4

この呼び出しがqueueコレクション変異するためです:QueueのJavaDocから

String string = queue.poll(); 

を:

を取得し、削除しこのキューの先頭を、またはこのキュー場合はnullを返します空です。 が(他は読まないと書き込み)排他的に実行する必要が書き込まれている間

読み取りロックは、複数のスレッドが安全にを読むことができるような状況で使用されることを意味しています。 pollに読み取りロックを使用しているため、複数のスレッドが非スレッドセーフLinkedListを同時に変更できるようになりました。

この場合、読み書きロックは正しい同期メカニズムではありません。

+0

はい、どうもありがとうございました。 – yura

関連する問題