Skip navigation links

Package com.electronwill.nightconfig.core.concurrent

Provides configurations that can be used from multiple threads.

See: Description

Package com.electronwill.nightconfig.core.concurrent Description

Provides configurations that can be used from multiple threads. This package exists in order to solve the following problem.

The problem

"Standard" configurations, created using methods of the core package such as Config.inMemory(), are not thread-safe. It is wrong to use them from multiple threads.

Even when a thread-safe Map is used to store the config's values, as that is the case with Config.inMemoryConcurrent(), there is no way to perform multiple operations in a consistent way, because their order is not guaranteed and they can overlap each other. On top of that, using sub-configurations in a single call, such as config.set("a.b.c", x) is problematic, because each subconfig has its own Map, the comments and the values are stored separately, and there is no mechanism that ensures the consistency of the whole configuration.

For instance, if a thread A executes

 
 config.set("a.b", "value");
 String a = config.get("a.b")
 
 
and another thread B executes
 
 String b = config.remove("a.b");
 
 
it is possible that thread A gets a = null, or that thread B gets b = null, or that they both get a value! This problem is even worse with complex operations and can lead to incorrect results or corrupted configurations.

The solution: using concurrent configurations

This package provides a new interface: ConcurrentConfig (and its commented version ConcurrentCommentedConfig). Classes that implement ConcurrentConfig offer the following features and guarantees: Every time that you have multiple operations to perform on the config, you should use the bulk methods. Here is an example:
 
 ConcurrentConfig config = new SynchronizedConfig();
 List<String> newPlayerList = config.bulkUpdate(conf -> {
     List<String> playerNames = conf.get("players");
     playerNames.add("NewPlayer");
     playerNames.remove("BadPlayer");
     conf.set("players", playerNames);
     return playerNames;
 });
 
 
Some configurations like StampedConfig and SynchronizedConfig also provide a way to atomically replace their entire content. At the moment, this feature is not part of the ConcurrentConfig interface.

Important caveats

In order to guarantee the safety of the operations and prevent any deadlock:
  1. In bulk operations, only the "view" provided to your bulk action can be used to read and modify the config (like in the example above). The reference to the original config object must not be used in the function given to bulkRead and bulkUpdate. Conversely, the view must not be used outside of the bulk operation.
  2. After replacement operations, the old configuration must not be used anymore, because its internal structure may have been totally or partially "moved" to the new configuration. See the documentation of SynchronizedConfig#replaceContentBy(com.electronwill.nightconfig.core.Config) for more information.
Since:
3.7.0
Skip navigation links