Shared resource in java

The Java EE 5 Tutorial

Web components, like most objects, usually work with other objects to accomplish their tasks. There are several ways they can do this. They can use private helper objects (for example, JavaBeans components), they can share objects that are attributes of a public scope, they can use a database, and they can invoke other web resources. The Java Servlet technology mechanisms that allow a web component to invoke other web resources are described in Invoking Other Web Resources.

Using Scope Objects

Collaborating web components share information by means of objects that are maintained as attributes of four scope objects. You access these attributes using the [get|set]Attribute methods of the class representing the scope. Table 4-3 lists the scope objects.

Web components within a web context. See Accessing the Web Context.

Web components handling a request that belongs to the session. See Maintaining Client State.

Subtype of javax.servlet.ServletRequest

Web components handling the request.

The JSP page that creates the object. See Using Implicit Objects.

Figure 4-1 shows the scoped attributes maintained by the Duke’s Bookstore application.

Figure 4-1 Duke’s Bookstore Scoped Attributes

Controlling Concurrent Access to Shared Resources

In a multithreaded server, it is possible for shared resources to be accessed concurrently. In addition to scope object attributes, shared resources include in-memory data (such as instance or class variables) and external objects such as files, database connections, and network connections.

Concurrent access can arise in several situations:

  • Multiple web components accessing objects stored in the web context.
  • Multiple web components accessing objects stored in a session.
  • Multiple threads within a web component accessing instance variables. A web container will typically create a thread to handle each request. If you want to ensure that a servlet instance handles only one request at a time, a servlet can implement the SingleThreadModel interface. If a servlet implements this interface, you are guaranteed that no two threads will execute concurrently in the servlet’s service method. A web container can implement this guarantee by synchronizing access to a single instance of the servlet, or by maintaining a pool of web component instances and dispatching each new request to a free instance. This interface does not prevent synchronization problems that result from web components accessing shared resources such as static class variables or external objects. In addition, the Servlet 2.4 specification deprecates the SingleThreadModel interface.

When resources can be accessed concurrently, they can be used in an inconsistent fashion. To prevent this, you must control the access using the synchronization techniques described in the Threads lesson in The Java Tutorial, Fourth Edition, by Sharon Zakhour et al. (Addison-Wesley, 2006).

The preceding section showed five scoped attributes shared by more than one servlet: bookDB, cart, currency, hitCounter, and orderCounter. The bookDB attribute is discussed in the next section. The cart, currency, and counters can be set and read by multiple multithreaded servlets. To prevent these objects from being used inconsistently, access is controlled by synchronized methods. For example, here is the Counter class, located at tut-install/javaeetutorial5/examples/web/bookstore1/src/java/com/sun/bookstore1/util/:

public class Counter < private int counter; public Counter() < counter = 0; >public synchronized int getCounter() < return counter; >public synchronized int setCounter(int c) < counter = c; return counter; >public synchronized int incCounter() < return(++counter); >>

Accessing Databases

Data that is shared between web components and is persistent between invocations of a web application is usually maintained by a database. Web components use the Java Persistence API to access relational databases. The data for Duke’s Bookstore is maintained in a database and is accessed through the database access class tut-install/javaeetutorial5/examples/web/bookstore1/src/java/com/sun/bookstore1/database/BookDBAO. For example, ReceiptServlet invokes the BookDBAO.buyBooks method to update the book inventory when a user makes a purchase. The buyBooks method invokes buyBook for each book contained in the shopping cart, as shown in the following code.

public void buyBooks(ShoppingCart cart) throws OrderException < Collection items = cart.getItems(); Iterator i = items.iterator(); try < while (i.hasNext()) < ShoppingCartItem sci = (ShoppingCartItem)i.next(); Book bd = (Book)sci.getItem(); String int quantity = sci.getQuantity(); buyBook(id, quantity); >> catch (Exception ex) < throw new OrderException("Commit failed: " + ex.getMessage()); >> public void buyBook(String bookId, int quantity) throws OrderException < try < Book requestedBook = em.find(Book.class, bookId); if (requestedBook != null) < int inventory = requestedBook.getInventory(); if ((inventory - quantity) >= 0) < int newInventory = inventory - quantity; requestedBook.setInventory(newInventory); >else < throw new OrderException("Not enough of " + bookId + " in stock to complete order."); >> > catch (Exception ex) < throw new OrderException("Couldn’t purchase book: " + bookId + ex.getMessage()); >>

To ensure that the order is processed in its entirety, the call to buyBooks is wrapped in a single transaction. In the following code, the calls to the begin and commit methods of UserTransaction mark the boundaries of the transaction. The call to the rollback method of UserTransaction undoes the effects of all statements in the transaction so as to protect the integrity of the data.

try < utx.begin(); bookDB.buyBooks(cart); utx.commit(); >catch (Exception ex) < try < utx.rollback(); >catch(Exception e) < System.out.println("Rollback failed: "+e.getMessage()); >System.err.println(ex.getMessage()); orderCompleted = false;> >

Copyright © 2010, Oracle and/or its affiliates. All rights reserved. Legal Notices

Источник

Thread Safety and Shared Resources

Code that is safe to call by multiple threads simultaneously is called thread safe. If a piece of code is thread safe, then it contains no race conditions. Race condition only occur when multiple threads update shared resources. Therefore it is important to know what resources Java threads share when executing.

Local Variables

Local variables are stored in each thread’s own stack. That means that local variables are never shared between threads. That also means that all local primitive variables are thread safe. Here is an example of a thread safe local primitive variable:

Local Object References

Local references to objects are a bit different. The reference itself is not shared. The object referenced however, is not stored in each threads’s local stack. All objects are stored in the shared heap.

If an object created locally never escapes the method it was created in, it is thread safe. In fact you can also pass it on to other methods and objects as long as none of these methods or objects make the passed object available to other threads.

Here is an example of a thread safe local object:

public void someMethod() < LocalObject localObject = new LocalObject(); localObject.callMethod(); method2(localObject); >public void method2(LocalObject localObject)

The LocalObject instance in this example is not returned from the method, nor is it passed to any other objects that are accessible from outside the someMethod() method. Each thread executing the someMethod() method will create its own LocalObject instance and assign it to the localObject reference. Therefore the use of the LocalObject here is thread safe.

In fact, the whole method someMethod() is thread safe. Even if the LocalObject instance is passed as parameter to other methods in the same class, or in other classes, the use of it is thread safe.

The only exception is of course, if one of the methods called with the LocalObject as parameter, stores the LocalObject instance in a way that allows access to it from other threads.

Object Member Variables

Object member variables (fields) are stored on the heap along with the object. Therefore, if two threads call a method on the same object instance and this method updates object member variables, the method is not thread safe. Here is an example of a method that is not thread safe:

public class NotThreadSafe < StringBuilder builder = new StringBuilder(); public add(String text)< this.builder.append(text); >>

If two threads call the add() method simultaneously on the same NotThreadSafe instance then it leads to race conditions. For instance:

NotThreadSafe sharedInstance = new NotThreadSafe(); new Thread(new MyRunnable(sharedInstance)).start(); new Thread(new MyRunnable(sharedInstance)).start(); public class MyRunnable implements Runnable < NotThreadSafe instance = null; public MyRunnable(NotThreadSafe instance)< this.instance = instance; >public void run() < this.instance.add("some text"); >>

Notice how the two MyRunnable instances share the same NotThreadSafe instance. Therefore, when they call the add() method on the NotThreadSafe instance it leads to race condition.

However, if two threads call the add() method simultaneously on different instances then it does not lead to race condition. Here is the example from before, but slightly modified:

new Thread(new MyRunnable(new NotThreadSafe())).start(); new Thread(new MyRunnable(new NotThreadSafe())).start();

Now the two threads have each their own instance of NotThreadSafe so their calls to the add method doesn’t interfere with each other. The code does not have race condition anymore. So, even if an object is not thread safe it can still be used in a way that doesn’t lead to race condition.

The Thread Control Escape Rule

When trying to determine if your code’s access of a certain resource is thread safe you can use the thread control escape rule:

If a resource is created, used and disposed within the control of the same thread, and never escapes the control of this thread, the use of that resource is thread safe.

Resources can be any shared resource like an object, array, file, database connection, socket etc. In Java you do not always explicitly dispose objects, so «disposed» means losing or null’ing the reference to the object.

Even if the use of an object is thread safe, if that object points to a shared resource like a file or database, your application as a whole may not be thread safe. For instance, if thread 1 and thread 2 each create their own database connections, connection 1 and connection 2, the use of each connection itself is thread safe. But the use of the database the connections point to may not be thread safe. For example, if both threads execute code like this:

check if record X exists if not, insert record X

If two threads execute this simultaneously, and the record X they are checking for happens to be the same record, there is a risk that both of the threads end up inserting it. This is how:

Thread 1 checks if record X exists. Result = no Thread 2 checks if record X exists. Result = no Thread 1 inserts record X Thread 2 inserts record X

This could also happen with threads operating on files or other shared resources. Therefore it is important to distinguish between whether an object controlled by a thread is the resource, or if it merely references the resource (like a database connection does).

Источник

Читайте также:  Error java error release version 5 not supported maven
Оцените статью