The Ground Rules
Threads and Synchronization
Threads and synchronization are discussed in the Miscellaneous lesson. This section discusses in general the issues that a service provider developer should be aware of regarding multithreaded access and the use of threads in service providers.
Context Implementations The JNDI defines the Context interface and subinterfaces to which a service provider must implement. Thread-safety with respect to concurrent access is an implementation issue. However, the JNDI does make some common sense recommendations on what the API user and service provider should expect.
The first rule means that the service provider need not worry about protecting access to resources used by a single Context instance against concurrent multithreaded access. Callers are responsible for synchronizing their accesses among themselves. This rule allows context implementations to be optimized for their most common thread usage mode.
- Access to a single Context instance must be synchronized.
- Access to separate Context instances need not be synchronized, even when the separate Context instances are seemingly related.
The second rule reminds service provider writers that when Context instances from the same context implementation share resources, those resources must be protected against concurrent access. For example, multiple Context instances commonly share the same underlying network connection. The network connection in this example would need to be protected against concurrent access. This rule is motivated by the fact that the callers cannot be expected to be aware of any underlying relationship between different Context instances and surely cannot be expected to synchronize access to different Context instances. Therefore the service provider must ensure that different Context instances behave as individual, independent entities and hide any implementation relationships.
Factory Implementations An object that implements any of the following interfaces and abstract classes (and their subinterfaces) should be reentrant. That is, multiple threads should be able to invoke methods on a single instance of a factory concurrently. Most factories are stateless, so this reentrancy requirement really is not much of an imposition on the implementation.
Use of Threads Threads are a useful tool for building system software such as a context implementation, especially when the implementation needs to deal with the network. In fact, threads are indispensable if a context implementation is to support event notification as described in the javax.naming.event package (see the Event Notification lesson).
You may use threads when building components of a service provider. However, be aware that the Java 2 Platform, Enterprise Edition, restricts components such as Enterprise JavaBeans from creating threads. This restriction means that if your service provider needs to create threads, then it should do so inside of a doPrivileged block. This allows the component's container to grant permission to the service provider for thread creation without granting the permission to the component.
Here is an example of a utility method for performing the thread creation inside of a doPrivileged block.
private Thread createThread(final Runnable r) { return (Thread) AccessController.doPrivileged( new PrivilegedAction() { public Object run() { return new Thread(r); } } ); }
The Ground Rules