Well, I'm not an expert by any means but threads is a very interesting topic to me. A couple of thoughts I have on that... and I'd appreciate any comment on these as it will further my understanding.
1) Method locks. When a method is synchronized then the lock is applied to the instance of the object in non-static context, and to the Class itself in static context. But in both cases, when you lock the method, you lock all other threads out of any and all synchronized methods (well...the same context, static or non-static being kept in mind) and they are locked out for the duration of the method, including any method calls invoked from within this method. That adds up to increased time spent "thumb-twiddling" by waiting threads. How much of that method's code really genuinely NEEDS to be done under lock protection? If you code well and make use of local variables you might be able to minimize the area that needs to be locked but, again, with method locks you lock the entire object(in non-static)/class(in static) for the duration of the method.
2) Block locks. Synchronizing a block of code allows two things: a) finer granularity of the area locked, and, b) selection/specification of a lock object rather than "this"(non-static) or the class(in static). The finer granularity part means that you only lock the code region that really needs to be locked. That means you have to code with a finer eye (any instance, static variables are treated as read-only, the working variables are local(on the stack ... so each thread has it's own), but that means threads can at least be concurrently active through portions of the called methods and contention for locks is minimized to just the required areas. Selection of a lock object means that you can have several locks protecting a different resource/set of resources. IN other words ... on any given thread execution though a particular method the resource might need to be synchronized, but, if the methods utilize different resources than those used by another method.... use a different lock. Any simple Object can be a lock.
3) THIS one may draw some heat. The Sierra/Bates SCJP warns against mixing static and non-static resources under method locks and I agree with that. But who hasn't come up with cases where you needed to do something that wasn't quite savory but you had a case for doing it that way? Well... if you instantiate an object with a static referrence and use it only for block synchronized locking.. it seems to me that as long as the code is written properly, both static and non-static resources could be synchronized by simply using that statically referenced object as the lock. I'll admit that I have not done any prototyping but it seems reasonable.
SCJP - 86% - June 11, 2009