Spiking Neuronal Net (SNN) with Java

Programming Requirements and Architectural Considerations

A central challenge in this context is the occurrence of *race conditions*. These arise when concurrent processes access shared resources in a competing manner, causing results to depend on the precise timing and ordering of these accesses.With a system that may involve up to a million virtual threads—each dynamically creating structures and modifying data—deterministic control over processing and outcomes becomes practically impossible. This leads to specific architectural and programming requirements.

In parallel systems, threads can interfere with one another when they operate on shared, mutable state. Such interference can cause non-deterministic behavior, including race conditions. Immutable data structures, such as Java Records, help mitigate these issues by eliminating shared mutable state.

Due to the high degree of parallelism, it is nearly impossible to define a moment in which the entire system is in a stable, well-defined state. This conflicts with SQL-based persistence mechanisms, which require consistent relational data at a specific point in time. A stable state is typically reached only when the system is shut down and all threads have terminated. Alternatively, the system could be designed around explicitly defined synchronization points rather than persisting data “at arbitrary moments”. However, because the SNN performs time-critical operations, waiting for threads to reach such points is not feasible.

For these reasons, I chose to treat data in isolation and persist it only when necessary. Furthermore, the system is designed to keep as much data as possible in memory for extended periods.

A central cache acts as the primary access point for all objects. It determines whether data must be evicted due to memory pressure and can asynchronously persist objects in the background before removal.

During runtime, the cache maintains the authoritative state of all objects. It loads data from persistence when needed and may evict objects from memory. Upon shutdown, all threads are stopped and the cache persists any remaining data.

This approach introduces certain risks. The “source of truth” resides in memory first and only later in the persistence layer. Because no additional validation occurs—as would be the case with SQL databases—the system forfeits guarantees regarding consistency, completeness, and validity of the data.

In this application, persistence serves exclusively to enable system restart, not to safeguard business‑critical information. Persisted data is merely an optional starting point.

A logical consequence is that the application operates with an *application time* rather than a *system time*. A learning process must not assume that a significant real-world time gap has passed between shutdown and restart. Thus, the system maintains a model time, but no external world time.

Given these considerations, I opted for a non-validating persistence mechanism in which all objects are stored independently. This is implemented using Java’s *Arena* API. This decision also yields substantial performance benefits. Initial measurements indicate that objects can be persisted within microseconds, whereas relational databases typically operate in the millisecond range.