Õ¾ÄÚËÑË÷: ÇëÊäÈëËÑË÷¹Ø¼ü´Ê
µ±Ç°Ò³Ãæ: ͼÊéÊ×Ò³ > Java Threads, Third Edition

3.5 Lock Scope - Java Threads, Third Edition

Previous Section  < Day Day Up >  Next Section

3.5 Lock Scope

Since we now have t he lock-related classes available in our arsenal, many of our earlier questions can now be addressed. Let's begin looking at the issue of lock scope by modifying our ScoreLabel class:

package javathreads.examples.ch03.example3;

...

public class ScoreLabel extends JLabel implements CharacterListener {

    ...

    public void newCharacter(CharacterEvent ce) {

        if (ce.source == generator) {

            try {

                scoreLock.lock( );

                // Previous character not typed correctly: 1-point penalty

                if (char2type != -1) {

                    score--;

                    setScore( );

                }

                char2type = ce.character;

            } finally {

                scoreLock.unlock( );

            }

        }

        // If character is extraneous: 1-point penalty

        // If character does not match: 1-point penalty

        else {

            try {

                scoreLock.lock( );

                if (char2type != ce.character) {

                    score--;

                } else {

                    score++;

                    char2type = -1;

                }

                setScore( );

            } finally {

                scoreLock.unlock( );

            }

        }

    } 

}

Since the lock() and unlock() method calls are explicit, we can move them anywhere, establishing any lock scope, from a single line of code to a scope that spans multiple methods and objects. By providing the means of specifying the scope of the lock, we can now move time-consuming and threadsafe code outside of the lock scope. And we can now lock at a scope that is specific to the program design instead of the object layout. In this example, we moved the source check outside of the lock, and we also split the lock in two, one for each of the conditions.

3.5.1 Synchronized Blocks

It is possible for the synchronized keyword to lock a block of code within a method. It is also possible for the synchronized keyword to specify the object whose lock is grabbed instead of using the lock of the object that contains the method. Much of what we accomplish with the Lock interface can still be done with the synchronized keyword. It is possible to lock at a scope that is smaller than a method, and it is possible to create an object just so that it can be used as an synchronization object. We can implement our last example just by using the synchronized keyword:

package javathreads.examples.ch03.example4;

...

public class ScoreLabel extends JLabel implements CharacterListener {

    ...

    // Definition for score lock deleted

    ...

    public synchronized void resetGenerator(CharacterSource newGenerator) {

        ...

    }

    public synchronized void resetTypist(CharacterSource newTypist) {

        ...

    }

    public synchronized void resetScore( ) {

        ...

    }

    private synchronized void setScore( ) {

        ...

    }

    public void newCharacter(CharacterEvent ce) {

        // Previous character not typed correctly: 1-point penalty

        if (ce.source == generator) {

            synchronized(this) {

                if (char2type != -1) {

                    score--;

                    setScore( );

                }

                char2type = ce.character;

            }

        }



        // If character is extraneous: 1-point penalty

        // If character does not match: 1-point penalty

        else {

            synchronized(this) {

                if (char2type != ce.character) {

                    score--;

               } else {

                   score++;

                   char2type = -1;

               }

               setScore( );

            }

        }

    } 

}

This syntax of the synchronized keyword requires an object whose lock is obtained. This is similar to our scoreLock object in the previous example. For this example, we are locking with the same object that was used for the synchronization of the method: the this object. Using this syntax, we can now lock individual lines of code instead of the whole method. We can also share data across multiple objects by locking on other objects instead, such as the data object to be shared.

Synchronized Methods Versus Synchronized Blocks

It is possible to use only the synchronized block mechanism even when we need to synchronize the whole method. For clarity in this book, we synchronize the whole method with the synchronized method mechanism and use the synchronized block mechanism otherwise. It is the programmer's personal preference to decide when to synchronize on a block of code and when to synchronize the whole method — with the caveat that it's always better to establish as small a lock scope as possible.


    Previous Section  < Day Day Up >  Next Section