The JavaTM Tutorial

| Start of Tutorial > Start of Trail > Start of Lesson | Search

Trail: Essential Java Classes
Lesson: Doing Two or More Tasks At Once: Threads

## Locking an Object

> The code segments within a program that access the same object from separate, concurrent threads are called critical sections. In the Java language, a critical section can be a block or a method and are identified with the `synchronized` keyword. The Java platform then associates a lock with every object that has synchronized code.

> In the producer/consumer example, the `put` and `get` methods of the `CubbyHole` (page 645) are the critical sections. The `Consumer` should not access the `CubbyHole` when the `Producer` is changing it, and the `Producer` should not modify it when the `Consumer` is getting the value. So `put` and `get` in the `CubbyHole` class should be marked with the `synchronized` keyword.

> Here's a code skeleton for the `CubbyHole` class:

> >     public class CubbyHole {
> >         private int contents;
> >         private boolean available = false;

> >         public synchronized int get() {
> >             ...
> >         }

> >         public synchronized void put(int value) {
> >             ...
> >         }
> >     }

> Note that the method declarations for both `put` and `get` contain the `synchronized` keyword. Hence, the system associates a unique lock with every instance of `CubbyHole` (including the one shared by the `Producer` and the `Consumer`). Whenever control enters a synchronized method, the thread that called the method locks the object whose method has been called. Other threads cannot call a synchronized method on the same object until the object is unlocked.

> So, when the `Producer` calls `CubbyHole`'s `put` method, it locks the `CubbyHole`, thereby preventing the `Consumer` from calling the `CubbyHole`'s `get` method:

> >     public synchronized void put(int value) {
> >         // CubbyHole locked by the Producer
> >         ..
> >         // CubbyHole unlocked by the Producer
> >     }

> When the `put` method returns, the `Producer` unlocks the `CubbyHole`.

> Similarly, when the `Consumer` calls `CubbyHole`'s `get` method, it locks the `CubbyHole`, thereby preventing the `Producer` from calling `put`:

> >     public synchronized int get() {
> >         // CubbyHole locked by the Consumer
> >         ...
> >         // CubbyHole unlocked by the Consumer
> >     }

> The acquisition and release of a lock is done automatically and atomically by the Java runtime system. This ensures that race conditions cannot occur in the underlying implementation of the threads, thus ensuring data integrity. Synchronization isn't the whole story. The two threads must also be able to notify one another when they've done their job. Learn more about that after a brief foray into reentrant locks.

| Start of Tutorial > Start of Trail > Start of Lesson | Search