Programming Tutorials Browser Tutorials Articles Struts Tutorials Hibernate Tutorials

  Tutorial: Programming Java threads in the real world, Part 7 - JavaWorld - April 1999

Programming Java threads in the real world, Part 7 - JavaWorld - April 1999

Tutorial Details:

Programming Java threads in the real world, Part 7
Programming Java threads in the real world, Part 7
By: By Allen Holub
Singletons, critical sections, and reader/writer locks
his month I'm going to tie up a few synchronization-related loose ends left over from my previous Java Toolbox installments in this series. I'll start out looking at singletons, or one-of-a-kind objects. These are surprisingly difficult to implement efficiently in a multithreaded environment, but are essential in most programs. ( java.awt.Toolkit is an example of a singleton.) Along the way, I'll also look at critical sections, or blocks of code -- as compared to objects -- that can be locked.
I'll finish up with a completely unrelated topic: reader/writer locks, which give you efficient, thread-safe access to read/write resources such as data structures and files. Reader/writer locks are simple enough to implement that I didn't want to devote an entire column to them, but they're essential in any multithreaded program that performs I/O operations, so I wanted to include them in the present series of articles. Reader/writer locks combined with the various semaphores and locks I've presented in previous installments of this series comprise a reasonably complete toolkit for solving thread-related synchronization problems.
Critical sections, singletons, and the Class object
So far in this series I've been concentrating on the monitor -- a means of locking an entire object while a body of code is being executed. The other essential sort of lock you should be aware of is the critical section. Critical sections are essential in implementing one-time initialization code when that code can be accessed from multiple threads.
A critical section is a chunk of code that can be executed by only one thread at a time. Compare this notion with a normal synchronized code block -- a monitor -- which is basically an exclusion semaphore that guards an entire object. Several threads can simultaneously execute a synchronized method, but only if the objects that are receiving the associated messages are different. In a critical section, the code itself is locked, not the object. Only one thread can be in the critical section at a time, even if the receiving objects are different. The mutex that guards a monitor is an object-level mutex; the mutex that guards a critical section is effectively a class-level mutex. Think of it this way: the code is defined in the class, not the object, so when you're locking the code itself, you're locking the entire class of objects. (By the way, I've seen authors get this wrong in print when they call a block of code inside a nonstatic method a "critical section." A block of code in a nonstatic method is part of the object's monitor; it is not a critical section.)
Static members In Java, the notion of a critical section is closely tied to that of a static member, so let's start there. Java, like all OO languages, supports two categories of fields and methods:
Class variables :
variables that control the state of all objects within a class.
Instance variables :
variables that control the state of a single object within a class.
A class variable is implemented in Java by placing a static keyword before its definition.
To best explain how the two types of variables are used in practice, an example seems in order. Back in the dark ages (the early 1990s) somebody had the bright idea that every window on a computer screen should use a different color scheme, even within a single application. Magenta backgrounds with yellow borders, turquoise backgrounds with chartreuse borders -- it make your eyes hurt. (The reasoning was that the users would somehow remember the color combinations and more easily identify the windows. Nice theory, but the human mind just doesn't work that way.) In this system, a window's color scheme is an "instance variable": every instance -- every window -- potentially has a different value for its color scheme.
Eventually, people came to their senses and made all the windows the same color. Now the color scheme is a "class variable." The entire class of window objects uses the same color scheme. If the scheme changes, then all the windows should change their appearance.
You can model the class-level behavior like this:
class Window // not the AWT window
{
private static Color foreground = SystemColor.windowText;
private static Color background = SystemColor.window;
synchronized static public change_color_scheme( Color foreground, Color background )
{
this.foreground = foreground;
this.background = background;
// code goes here that tells all the extant Window objects to
// redraw themselves with the new color scheme.
}
}
There are several problems with this simplistic approach, however, the first being threading.
Java creates a Class class object for every class in your system, and the static fields are members of this Class object. A Class object is a real object: It has methods (declared static in the class definition) and state (defined by the static fields). The Class object also has its own monitor. When you call a synchronized static method, you enter the monitor associated with the Class object. This means that no two synchronized static methods can access the static fields of the class at the same time. You can also lock the Class object explicitly, like this:
synchronized( Window.class )
{ // modify static fields here
}
Unfortunately, the Class -level monitor is in no way connected to the monitors of the various instances of the object, and a synchronized , but nonstatic, method can also access the static fields. Entering the synchronized nonstatic method does not lock the Class object. Why is this a problem? Well, in the previous example, it would appear to be harmless to omit the static (but not the synchronized ) from the definition of change_color_scheme() since the static fields will be modified, even if the modifying method isn't static . Appearances are deceiving, though. If two threads simultaneously send change_color_scheme() messages to two different objects of class Window , a race condition results, and the color scheme will be in an unknown state. In other words, the individual Window objects are locked, but locking a Window object does not lock the corresponding Class object (which contains the class variables), and the static fields are unguarded. Consequently, we have two threads modifying two variables at the same time.
After threading, the second problem with the naive implementation is that there's no way to guarantee that all the existing objects stay in synch with changes to the class variables. A sloppy programmer can add an instance method (one that is not static ) to the Window class, and that instance method can change the foreground or background fields without notifying the other windows, or even without updating its own color.
You can fix both the race-condition and lack-of-update problems by encapsulating the two static fields in a class of their own:
class Color_scheme
{
private Color foreground = SystemColor.windowText;
private Color background = SystemColor.window;
/*package*/ synchronized change_color_scheme(
Color foreground, Color background )
{
this.foreground = foreground;
this.background = background;
// code goes here that tells all the extant Window objects to
// redraw themselves with the new color scheme.
}
}
class Window // not the AWT window
{
static Scheme color_scheme = new Color_scheme();
static change_color_scheme( Color foreground, Color background )
{ scheme.change_color_scheme( foreground, background );
}
}
Now there's no way to modify the foreground or background color without notifying the other windows. Note that this is one of the few cases in which you must use package access rather than an inner class. Had Color_scheme been an inner class of Window , direct access to foreground and background would still be possible from methods of Window . This approach also has the advantage of making the monitor that controls the Color_scheme more visible -- it's obviously the one associated with the explicit Color_scheme object, not the one associated with the Window .
Singletons
There's another problem with the earlier code, however. We really want only one Color_scheme to exist, ever. In the earlier code, I've done it accidentally by making the reference static and only calling new once, but I'd really like to guarantee that only one instance of the object can exist. The Gang of Four's (see Resources ) Singleton pattern describes exactly this situation. Two excerpts from the Gang of Four book are relevant. The "Intent" section in the Gang of Four book's chapter on singletons states:
Ensure a class only has one instance, and provide a global point of access to it.
and the "Consequences" section says:
[Singleton] permits a variable number of instances. The pattern makes it easy to change your mind and allow more than one instance of the singleton class. Moreover, you can use the same approach to control the number of instances that the application uses. Only the [Instance] operation that grants access ot the singleton instance needs to change.
That excerpt from the "Consequences" section is interesting because it allows a Class object to be considered a singleton, even though there's more than one instance of the Class class in the program. It's guaranteed that there will be only a single instance of Class for a given class, so it's a singleton: Some_class.class (the "operation that grants access") always evaluates to the same Class object. The static fields and methods, since they are members of the Class object, define the state and methods of the singleton object as well. Exploiting this reasoning, I can ensure that only one instance of the Color_scheme exists by moving everything into the Class object (making everything static ):
class Color_scheme
{
private static Color foreground = Syste


 

Read Tutorial at: Click here to view the tutorial

Rate Tutorial:
Programming Java threads in the real world, Part 7 - JavaWorld - April 1999

View Tutorial:
Programming Java threads in the real world, Part 7 - JavaWorld - April 1999

Related Tutorials:

Integrating Databases
Integrating Databases
 
3D graphics programming in Java, Part 3: OpenGL
3D graphics programming in Java, Part 3: OpenGL
 
Programming Java threads in the real world, Part 8
Programming Java threads in the real world, Part 8
 
Object-oriented language basics, Part 7
Object-oriented language basics, Part 7
 
I want my AOP!, Part 1
I want my AOP!, Part 1
 
I want my AOP!, Part 3
I want my AOP!, Part 3
 
Achieve strong performance with threads, Part 1
Achieve strong performance with threads, Part 1
 
Achieve strong performance with threads, Part 2
Achieve strong performance with threads, Part 2
 
Best tools for mobile application development
Best tools for mobile application development
 
J2SE 1.4.1 boosts garbage collection
J2SE 1.4.1 boosts garbage collection
 
Add concurrent processing with message-driven beans
Add concurrent processing with message-driven beans
 
Good, but obsolete
Good, but obsolete
 
Java programming dynamics, Part 7: Bytecode engineering with BCEL
Java programming dynamics, Part 7: Bytecode engineering with BCEL Apache BCEL lets you get to the details of JVM assembler language for classworking The Apache Byte Code Engineering Library (BCEL) lets you dig into the bytecode of Java classes. You
 
Real World HTML Parser
Real World HTML Parser The two fundamental use-cases that are handled by the parser are extraction and transformation (the syntheses use-case, where HTML pages are created from scratch, is better handled by other tools closer to the source of data). Whil
 
Attribute-Oriented Programming with Java 1.5, Part 1
In this article, I will consider the case of a status-bar component embedded in a GUI application. I will explore a number of different ways to implement this status reporter, starting with the traditional hard-coded idiom. Along the way, I will introduce
 
JDBC scripting, Part 2
JDBC scripting, Part 2 Programming and Java scripting in JudoScript Summary JudoScript is a rich functional scripting language, and an easy and powerful general programming and Java scripting language. JudoScript's power comes from its synergy of
 
The ABCs of Synchronization, Part 1
Threads may execute in a manner where their paths of execution are completely independent of each other. Neither thread depends upon the other for assistance. For example, one thread might execute a print job, while a second thread repaints a window. And
 
Commons-Math: The Jakarta Mathematics Library
Commons-Math: The Jakarta Mathematics Library The Java programming language and the math extensions in Commons Lang provide implementations for only the most basic mathematical algorithms. Routine development tasks such as computing basic statistics or s
 
An Introduction to Java Object Persistence with EJB
The 'impedance mismatch' between relational databases' tabular orientation and object-oriented Java's hierarchical one is a perennial problem for which the Java world has several good solution offerings. This article, the first in a three-part series, wil
 
Understanding MIDP System Threads
Describes the multi-threaded aspects of the J2ME application environment. Understanding the interactions between systems threads, user-interface and application threads will help in avoiding MIDlet deadlock.
 
Site navigation
 

 

Send your comments, Suggestions or Queries regarding this site at roseindia_net@yahoo.com.

Copyright © 2006. All rights reserved.