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()));
}
}
答案 0 :(得分:4)
这是因为此调用会改变queue
集合:
String string = queue.poll();
来自Queue JavaDoc:
检索并删除此队列的头部,如果此队列为空,则返回null。
读锁定意味着在多个线程可以安全地读取的情况下使用,而写入必须独占执行(没有其他读取和写入)。因为您正在使用读取锁定poll
队列(写入操作!),所以您实际上允许多个线程同时修改非线程安全的LinkedList
。
在这种情况下,读写锁不是正确的同步机制。