【问题标题】:Why this ReadWriteLock example dosen't work?为什么这个 ReadWriteLock 示例不起作用?
【发布时间】:2011-07-10 21:56:58
【问题描述】:

LinkedList 在尝试轮询数据时抛出异常。但我认为我正确地使用了读/写锁概念。这段代码有什么问题?

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()));

    }
}

【问题讨论】:

  • 请在发布问题之前粘贴异常并清理您的代码。谢谢。

标签: java multithreading concurrency locking


【解决方案1】:

这是因为这个调用改变了queue 集合:

String string = queue.poll();

来自QueueJavaDoc:

检索并移除此队列的头部,如果此队列为空,则返回 null。

读锁适用于多个线程可以安全地读取,而写入必须以独占方式执行(没有其他读取和写入)的情况。因为您正在使用对poll 队列的读锁定(写操作!),所以您实际上允许多个线程同时修改非线程安全的LinkedList

在这种情况下,读写锁不是正确的同步机制。

【讨论】:

    猜你喜欢
    • 2011-04-10
    • 2018-06-12
    • 2014-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多