Threads And The Java Language
To create a thread using the Java language, you instantiate an object of type Thread
(or a subclass) and send it the start()
message. (A program can send the start()
message to any object that implements the Runnable
interface.) The definition of each thread's behavior is contained in its run()
method. A run method is equivalent to main()
in a traditional program: a thread will continue running until run()
returns, at which point the thread dies.
Locks
Most applications require threads to communicate and synchronize their behavior to one another. The simplest way to accomplish this task in a Java program is with locks. To prevent multiple accesses, threads can acquire and release a lock before using resources. Imagine a lock on the copy machine for which only one worker can possess a key at a time. Without the key, use of the machine is impossible. Locks around shared variables allow Java threads to quickly and easily communicate and synchronize. A thread that holds a lock on an object knows that no other thread will access that object. Even if the thread with the lock is preempted, another thread cannot acquire the lock until the original thread wakes up, finishes its work, and releases the lock. Threads that attempt to acquire a lock in use go to sleep until the thread holding the lock releases it. After the lock is freed, the sleeping thread moves to the ready-to-run queue.
In Java programming, each object has a lock; a thread can acquire the lock for an object by using the synchronized
keyword. Methods, or synchronized blocks of code, can only be executed
by one thread at a time for a given instantiation of a class, because
that code requires obtaining the object's lock before execution.
Continuing with our copier analogy, to avoid clashing copiers, we can
simply synchronize access to the copier resource, allowing only one
worker access at a time, as shown in the following code sample. We
achieve this by having methods (in the Copier
object) that modify the copier state be declared as synchronized methods. Workers that need to use a Copier
object have to wait in line because only one thread per
Copier object can be executing synchronized code.
|
Fine-grain locks
Often, using a lock at the object level is too coarse. Why lock up
an entire object, disallowing access to any other synchronized method
for only brief access to shared resources? If an object has multiple
resources, it's unnecessary to lock all threads out of the whole object
in order to have one thread use only a subset of the thread's
resources. Because every object has a lock, we can use dummy objects as
simple locks, as shown here:
|
These methods need not be synchronized at the method level by declaring the whole method with the synchronized
keyword; they are using the member locks, not the object-wide lock that a synchronized method acquires.
View Writing Multithreaded Java Applications Discussion
Page: 1 2 3 4 5 6 7 Next Page: Semaphores