1

Note: I'm not looking for workarounds; I'm sure I can find other methods if necessary. I simply feel like I'm missing something fundamental or quirky and I want to know what I'm missing. Or if there is a way to use the debugger to get more info that would be nice too. Thanks!

I'm having an issue with use of synchronized. I'm receiving deadlock but it seems utterly impossible. I've placed print statements before each and every synchronized call, just inside each call, and just before exiting so I can see who all holds which synchronized objects. I'm finding that it will not go inside one of my synchronized calls even though no one currently holds the lock on the object. Are there some kind of quirks that I'm missing or illegal nesting operations? Here's the jist of what I am doing.

Oh yeah, and the oddest thing is that removing the two "busyFlagObject" synchronizations makes it work fine...

Thread 1:

public void DrawFunction()
{
    synchronized(drawObject)
    {
        ...
        // Hangs here though nobody has a lock on this object
        synchronized(animationObject)
        {

        }
    }
}

Thread 2:

public void AnotherFunction()
{
    synchronized(busyFlagObject)
    {
        // Calls a function that also uses this same Synchronized call
        synchronized(busyFlagObject)
        {
            // Calls another function that uses another Synchronized call
            // Hangs here waiting for the draw function to complete which it SHOULD 
            // be able to do no problem.
            synchronized(drawObject)
            {

            }

            // Never gets to this one assuming the Log statements don't 
            // buffer and aren't flushed but still shouldn't be a problem anyway.
            synchronized(animationObject)
            {

            }
        }
    }
}
CodeMonkey
  • 1,795
  • 3
  • 16
  • 46
  • what happens if you remove one of nested `busyFlagObject` syncronization? – Archer Jan 09 '13 at 00:08
  • are you sure that the problem is in your synchronized blocks and not in functions you call from them? Have you tryed remove everything except thread sync and logs? – Leonidos Jan 09 '13 at 00:22
  • Removing only one busyFlagObject still results in the same deadlock. I have not tried removing the code within the functions, but it's only as deep as I have shown. Everything not shown is merely math operations or variable setting. I know that it hangs on the synchronized calls because the debugger shows both threads stuck at them. – CodeMonkey Jan 09 '13 at 00:30
  • Are you sure that `busyFlagObject` and `animationObject` are not the same object by accident? (Similarly check this for all other combinations of objects, do different names in your code certainly imply different objects?) Are you sure that only one instance of Thread 1 and Thread 2 is running? – us2012 Jan 09 '13 at 00:38
  • Yes. All my synchronized objects are Booleans that are set only once at declaration and never altered again. – CodeMonkey Jan 09 '13 at 00:51
  • Back to the roots - comment out all code that actually does stuff, just leave the synchronized blocks and the print statements to make sure the blocks aren't empty (so they cannot be optimized away). Does the deadlock still happen? – us2012 Jan 09 '13 at 01:15
  • Don't know if I'm saying something stupid right now, but can't you just synchronize the method? – NickL Jan 09 '13 at 06:47

1 Answers1

2

Run your app under the debugger or use "jstack" from the JDK tools. That will show you directly which threads wait for locks and which hold locks, so we don't have to guess where your problem is :-)

That said, you mention you synchronize on Boolean. Keep in mind that the class is intended to only have two instances, and many things (particularly boxing) will implicitly change your Boolean instance to the "shared" value. Are you sure your lock objects are not the same instance? You might consider using new Object() as your monitor object.

It's worth noting that this isn't the only place that this can happen and there's a good entry on this problem in Java Concurrency in Practice, specifically with string interning, that I'm failing to find a link to at the moment. Don't use a type that isn't under your control as something it wasn't intended to do :-)

Steven Schlansker
  • 37,580
  • 14
  • 81
  • 100
  • I did use the debugger and found where my two threads were deadlocked. One was deadlocked on animationObject and the other on drawObject. The one locked at animationObject does indeed hold the drawObject, but the other does not hold the animationObject thus there should be no deadlock. If there is a method of seeing who "holds the lock" that would be great but I don't know how beyond seeing where the threads are locking. I'm not sure I fully understand what you mean about the Booleans, but I will attempt new Object() and see if it makes a difference. Thanks! – CodeMonkey Jan 09 '13 at 15:30
  • Oh! I think I understand what you're saying now. Is it true then that "private Boolean bawb = true" is the same instance as "private Boolean phred = true" and would only differ from each other if one was false? That would definitely account for the problem! – CodeMonkey Jan 09 '13 at 17:11
  • @CodeMonkey: yep, that's exactly the problem :-) – Steven Schlansker Jan 09 '13 at 19:31