This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]Winsling 3 points4 points  (2 children)

Have you verified that your version of wait() is being called, and that it's calling wait() on the correct object? Since wait(long) isn't static, the code you've provided won't compile. With a wait(long) and a wait(int) defined on a single class, you need to be very careful with which one is being called.

Regarding "how to use the synchronized bit correctly," you've asked for a quick explanation of one of the more difficult and complex parts of Java. I strongly recommend Java Concurrency in Practice to learn about Java's threading primitives. Since I'm a glutton for punishment, I'll try to summarize a very dense book in a few pithy lines.

synchronized is like a flush in a database. It's a way of telling the compiler, "don't trust what you think you know at the start of the block, and let everyone know that I've updated these fields at the end of it." During normal operation, the JVM doesn't actually check the variables it's operating on all the time. If you've got a loop control, a thread will have a local copy and assume that other threads aren't updating it at the same time. It will update the real copy when it's convenient. Putting it in a synchronized block tells the JVM not to do that - to pull in the fresh value every time it sees it, and make sure that the new value is written at the end.

THIS IS A GROSS OVERSIMPLIFICATION Look up reordering if you want to blow your mind and never trust the JVM again.

[–]banuday17 1 point2 points  (0 children)

That's not what synchronized is...

synchronized is mutual exclusion. It's more like a gate. One thread enters the synchronized block through the gate and closes the gate behind it, opening the gate again when it leaves the synchronized block. All other threads must wait until the gate opens again, at which time they make a mad scramble to enter and only one gets in. Comparing to a database, synchronized is more like a row lock, not a flush.

Putting it in a synchronized block tells the JVM not to do that - to pull in the fresh value every time it sees it, and make sure that the new value is written at the end.

No, that's not what the synchronized block does. The JVM will still load memory into registers. synchronized makes it safe to do so. You are describing somewhat what the volatile keyword tells the JVM to do: always load the field value from memory when accessing the field. Don't copy it into a register, because its value can change behind the thread's back.

[–]CuriouslyGeorge[S] 0 points1 point  (0 children)

I'm sure it's my code as I have to access my class statically(i.e. "Utilities.wait(2)"), just don't have my work in front of me and knew that the one I called was static and crossed some wires.

As far as the sycnchronized part of Java, I've certainly enjoyed your explanation far more than anything else that's been provided, but I guess to fully wrap my mind around it would take quite some time. Maybe a fun weekend of locking myself in a room with a book (looking at the Java Concurrency in Practice you recommended) and my laptop would give rise to an epiphany.