[英]Strange behavior with Java Synchronization (Lock, Condition)
I am just trying to model a simple readers / writers scenario. 我只是想为一个简单的读者/作家场景建模。
Here is the code: 这是代码:
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ReadersWriters implements Solution {
private final static Lock readerLock = new ReentrantLock();
private final static Lock writerLock = new ReentrantLock();
private final static Condition noReader = readerLock.newCondition();
private static CountDownLatch countDown;
private static volatile int readerCount=0;
public static class Reader implements Runnable {
private static int count=1;
private int id = count++;
@Override
public void run() {
int readCount = (int) (Math.random()*20);
while (readCount > 0) {
readCount--;
writerLock.lock();
try {
readerLock.lock();
try {
readerCount++;
} finally {
readerLock.unlock();
}
} finally {
writerLock.unlock();
}
System.out.println("Reader "+id+" reading ("+readerCount+" readers)");
try {
Thread.sleep((long) (Math.random()*500));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Reader "+id+" done");
readerLock.lock();
try {
readerCount--;
noReader.signalAll();
} finally {
readerLock.unlock();
}
try {
Thread.sleep((long) (Math.random()*500));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
countDown.countDown();
}
}
public static class Writer implements Runnable {
private static int count=1;
private int id = count++;
@Override
public void run() {
int writeCount = (int) (Math.random()*20);
while (writeCount>0) {
writeCount--;
writerLock.lock();
try {
readerLock.lock();
try {
while (readerCount>0) {
noReader.await();
}
System.out.println("Writer "+id+" writing");
try {
Thread.sleep((long) (Math.random()*500));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Writer "+id+" done");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
readerLock.unlock();
}
} finally {
writerLock.unlock();
}
try {
Thread.sleep((long) (Math.random()*500));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
countDown.countDown();
}
}
public static void main(String []args) {
Executor exec = Executors.newCachedThreadPool();
int numReaders = 10;
int numWriters = 4;
countDown = new CountDownLatch(numReaders+numWriters);
for (int i=0; i<numReaders; i++) {
exec.execute(new Reader());
}
for (int i=0; i<numWriters; i++) {
exec.execute(new Writer());
}
try {
countDown.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
I know I could also use ReadWriteLock
, but that's not the point... 我知道我也可以使用
ReadWriteLock
,但这不是重点...
My problem is that in the log, I see things like this: 我的问题是在日志中,我看到这样的事情:
Writer 4 writing
Writer 4 done
Reader 9 reading (1 readers)
Reader 8 reading (3 readers)
Reader 5 reading (2 readers)
Reader 8 done
Reader 5 done
Reader 9 done
Writer 3 writing
Writer 3 done
And I really don't see how this could happen... Is it just console prints that are getting mixed up or I am really missing something here? 而且我真的不知道这怎么可能...是只是控制台打印变得混乱,还是我在这里真的缺少什么?
Your System.out.println
calls in the Reader aren't synchronised. 阅读器中的
System.out.println
调用不同步。 What, exactly, worries you here? 到底是什么让您担心?
I believe your problem is about these few lines right? 我相信您的问题与这几行有关吗?
Reader 9 reading (1 readers)
Reader 8 reading (3 readers)
Reader 5 reading (2 readers)
which you expect it to be 1,2 and then 3 readers. 您希望它是1,2,然后是3个读者。
In brief, the problem is because your printing is not part of the synchronization block. 简而言之,问题是因为您的打印不属于同步块。
To give an example of possible cause base on your code, here it is: 在您的代码的基础上给出一个可能的原因示例,这里是:
writerLock.lock();
try {
readerLock.lock();
try {
readerCount++;
} finally {
readerLock.unlock();
}
} finally {
writerLock.unlock();
}
System.out.println("Reader "+id+" reading ("+readerCount+" readers)");
for the above piece of code, in brief, update of readerCount
is guarded by writerLock
. 用于上述代码段,在短暂的更新
readerCount
由把守writerLock
。 However it is possible that: 但是有可能:
READER8 READER5
(readerCount = 1 at this point)
lock writerLock
readerCount++ (=2)
unlock writerLock
lock writerLock
update readerCount to 3
unlock writerLock
sysout of readerCount (3)
lock writerLock
readerCount-- (=2)
sysout of readerCount (2)
unlock writerLock
lock writerLock
readerCount-- (=1)
unlock writerLock
Not hard to imagine why the number looks strange. 不难想象为什么这个数字看起来很奇怪。
Put the system out statement in the locked scope, just after readerCount++, will give u result expected. 将system out语句放在readerScope ++之后的锁定范围内,将给您预期的结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.