Harvey Adcock Harvey Adcock - 3 months ago 11
Java Question

synchronized block for a while loop's condition

I'm trying to fix a piece of code I've written that currently has race conditions. In doing so I need to put the condition of a

while
loop in a
synchronized
block, however I don't want to synchronise the whole
while
block since that would starve other threads of the resource, which they need. I can't figure a reasonable way of doing it without repetition or
break
s in places that slightly obscure the control flow. Below is the gist of the problem code:

while ((numRead = in.read(buffer)) != -1) {
out.write(buffer);
}


and I need to synchronise the use of
in
. The two potential solutions I could think of (but don't think they're very good) are:

synchronized (this) {
numRead = in.read(buffer);
}
while (numRead != -1) {
out.write(buffer);
synchronized (this) {
numRead = in.read(buffer);
}
}


which has undesirable repetition, and this:

while (true) {
synchronized (this) {
numRead = in.read(buffer);
}
if (numRead == -1)
break;
else
out.write(buffer);
}


which isn't great for readability. Any suggestions?

Answer

Try it like below.

public testMyMethod () {
    byte[] buffer = new int[1024];
    int numRead = -1;
    while ((numRead = readInput(buffer)) != -1) {
        out.write(buffer);
    }
}

//first method
synchronized int readInput(byte[] buffer) {
    return in.read(buffer);
}

//second method, more performant about 3 times, just the synchronization parts
private static final ReentrantLock inputLock = new ReentrantLock();

int readInput(byte[] buffer) {
    int readLen = -1;
    inputLock.lock();
    try {
        readLen = in.read(buffer);
    } finally {
        inputLock.unlock();
    }
    return readLen;
}