If a thread tries to enter a synchronized method and the lock is already taken, the thread is said to be blocked on the object's lock. Essentially, the thread goes into a kind of pool for that particular object and has to sit there until the lock is released and the thread can again become runnable/running.Just because a lock is released doesn't mean any particular thread will get it.There might be three threads waiting for a single lock, for example, and there's no guarantee that the thread that has waited the longest will get thelock first.When thinking about blocking, it's important to pay attention to which objects are being used for locking.
Threads calling non-static synchronized methods in the same class will only block each other if they're invoked using the same instance. That's because they each lock on this instance, and if they're called using two different instances, they get two locks, which do not interfere with each other.
Threads calling static synchronized methods in the same class will always block each other—they all lock on the same Class instance.
A static synchronized method and a non-static synchronized method will not block each other, ever. The static method locks on a Class instance while the non-static method locks on the this instance—these actions do not interfere with each
other at all.
For synchronized blocks, you have to look at exactly what object has been used for locking. (What's inside the parentheses after the word synchronized?) Threads that synchronize on the same object will block each other. Threads that synchronize on different objects will not.
You don't need to worry about local variables—each thread gets its own copy of a local variable. Two threads executing the same method at the same time will use different copies of the local variables, and they won't bother each other. However, you do need to worry about static and non-static fields, if they contain data that can be changed.
For changeable data in a non-static field, you usually use a non-static method to access it. By synchronizing that method, you will ensure that any threads trying to run that method using the same instance will be prevented from simultaneous access. But a thread working with a different instance will not be affected, because it's acquiring a lock on the other instance. That's what we want.Threads working with the same data need to go one at a time,but threads working with different data can just ignore each other and run whenever they want to; it doesn't matter.
Remember that a static synchronized method and a non-static synchronized method will not block each other—they can run at the same time. Similarly, if you access a static field using a non-static method, two threads might invoke that method using two different this instances. Which means they won't block each other, because they use different locks. Which means two threads are simultaneously accessing the same static field—exactly the sort of thing we're trying to prevent.
Access to static fields should be done from static synchronized methods. Access to non-static fields should be done from non-static synchronized methods.
wait(), notify(), and notifyAll() must be called from within a synchronized context! A thread can't invoke a wait or notify method on an object unless it owns that object's lock.
Classes and their Methods
| ||
Class Object
|
Class Thread
|
Interface Runnable
|
wait()
|
start()
|
run()
|
notify()
|
yield()
| |
notifyAll()
|
sleep()
| |
join()
|