Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Value does not update in while loop unless printed out [duplicate]

Ok, so I have a monitoring thread that checks a ArrayList size and does something after that size goes greater than a certain number. The problem I am having right now is the size value is never updated unless I have a print statement in my loop. Here is some code to show what exactly I have going.

while(working) {
    // Get size function just returns the size of my list in my t class
    int size = t.getSize();
    if (size >= 10) {
        //DO STUFF
    }
}

This above code does not work. It never goes into the if statement. However, this works fine:

while(working) {
    // Get size function just returns the size of my list in my t class
    int size = t.getSize();
    System.out.println(size);
    if (size >= 10) {
        //DO STUFF
    }
}

EDIT: getSize() code:

public ArrayList<byte[]> myQueue = new ArrayList<byte[]>();

public int getSize() {
    return myQueue.size();      
}

NOTE: I have another thread running that is updating and adding to my list in my t class.

Any help? this is really annoying to have it spitting out numbers when I am trying to debug in the console.

like image 969
ageoff Avatar asked May 30 '13 14:05

ageoff


2 Answers

If the only thing changing between your working and non working code is the println statement, then you almost certainly have a threading issue. The System.out.println() statement adds a small pause which may coincidentally cause it to behave, but is not solving the issue. You could do something like:

try {
    Thread.sleep(10);
} catch (InterruptedException ex) {
}

...in place of this and check for the same behaviour, if indeed it is the same then this pretty much confirms the threading issue. However, as pointed out below println() also does a few other things such as causing a memory barrier, so this isn't a foolproof test. Another, perhaps better check could be to temporarily swap out ArrayList for Vector, which is thread safe - though this is a legacy collection so not recommended for use in the final code.

If this is the case, it sounds like you're not synchronising on ArrayList calls properly - ArrayList is not a thread safe collection. Whenever you read or write to the list, do it inside a synchronized block like so, synchronizing on the list:

synchronized(list) {
    list.whatever();
}

...which will ensure that only one thread can access the ArrayList at once, hopefully solving the threading issue.

like image 185
Michael Berry Avatar answered Nov 03 '22 01:11

Michael Berry


ArrayList is not synchronized, or otherwise prepared for use in two threads at once. In JLS terms, there is no happens-before relationship between the addition of elements in one thread and a size() call in another thread.

The cleanest solution would be to use a synchronized List implementation. You can either use Vector, or create a synchronized wrapper around your ArrayList using Collections.synchronizedList().

like image 33
Patricia Shanahan Avatar answered Nov 02 '22 23:11

Patricia Shanahan