Concurrency and thread safety

Gosu provides APIs that protect shared data from access from multiple threads.

If more than one Gosu thread interacts with data structures that another thread needs, you must ensure that you protect data access to avoid data corruption. Because this topic involves concurrent access from multiple threads, this issue is called concurrency. Code that is designed to safely get or set concurrently accessed data is called thread safe.

The most common situation that requires concurrency handling is the use of data in class static variables. Static variables are variables that are stored once for a class rather than once for each instance of the class. If multiple threads on the same Java virtual machine access this class, you must ensure that simultaneous accesses to this data safely get or set the data.

If you are certain that static variables or other shared data are necessary, you must ensure that you synchronize access to static variables. Synchronization refers to locking access between threads to shared resources such as static variables. For example, if you need to manage a single local memory cache that multiple threads use, you must carefully synchronize all reads and writes to shared data.

Warning: Static variables can be extremely dangerous in a multi-threaded environment. Using static variables in a multi-threaded environment can cause problems in a production deployment if you do not properly synchronize access. If such problems occur, they are extremely difficult to diagnose and debug. Timing in an multi-user multi-threaded environment is difficult, if not impossible, to control in a testing environment.

In a Guidewire application, some contexts always require proper synchronization. For example, in a plugin implementation exactly one instance of that plugin exists in the Java virtual machine on each server. Your plugin code must have the following attributes:

  • Your plugin must support multiple simultaneous calls to the same plugin method from different threads. You must ensure multiple calls to the plugin never access the same shared data. Alternatively, protect access to shared resources so that two threads never access it simultaneously.
  • Your code must support multiple simultaneous calls to a plugin instance. For example, PolicyCenter might call two different plugin methods at the same time. You must ensure multiple method calls to the plugin never access the same shared data. Alternatively, protect access to shared resources so that two threads never actually access it simultaneously.
  • Your plugin implementation must support multiple user sessions. Do not assume shared data or temporary storage is unique to one user request, which is one HTTP request from a single user.
Gosu provides the following types of concurrency APIs to support writing thread-safe code:
Request and session variables
The classes RequestVar and SessionVar in the package gw.api.web synchronize and protect access to shared data. These APIs return a variable that is stored in either the request or the session.
Lazy concurrent variables
The LockingLazyVar class (in gw.util.concurrent) implements what is known as a lazy variable. Gosu does not construct a lazy variable until the first time any code uses the variable. Because the LockingLazyVar class uses the Java concurrency libraries, access to the lazy variable is thread-safe. The LockingLazyVar class wraps the double-checked locking pattern in a type-safe holder.
Concurrent cache
The Cache class in gw.util.concurrent declares a cache of values that you can look up quickly and in a thread-safe way. It declares a concurrent cache similar to a Least Recently Used (LRU) cache. Because the Cache class uses the Java concurrency libraries, access to the concurrent cache is thread-safe.
Warning: Caches can cause subtle problems. Use caches only as a last resort for performance.
Support for Java monitor locks, reentrant locks, and custom reentrant objects
Gosu provides access to Java-based classes for monitor locks and reentrant locks in the Java package java.util.concurrent. Gosu using clauses provide access to these classes and properly handle cleanup if exceptions occur. Gosu also provides a readable syntax for creating custom objects for reentrant object handling.

Concurrency API does not synchronize across clusters

None of these concurrency APIs affect shared data across clusters. In practice, the only data shared across clusters is entity data. PolicyCenter includes built-in systems to synchronize and intelligently cache entity data across a cluster.

Do not attempt to synchronize Guidewire entities

Never try to synchronize access to Guidewire entities defined in the data model configuration files. PolicyCenter automatically manages synchronized access and entity loading and caching, both locally and across a cluster if you use clusters.

A transaction bundle based on the class gw.transaction.Bundle is not thread-safe. Be aware of any concurrency issues when accessing entity instances in a bundle or committing those instances to the database. If multiple users can access the entity instances in a bundle simultaneously, you must use external synchronization to ensure reading and writing correct data, such as for property values.

Warning: Use external synchronization to ensure data integrity for concurrent access to entity instances in a transaction bundle.

See also