# Understanding Synchronization and Data Access with system.util.getGlobals

**URL:** <https://forum.inductiveautomation.com/t/understanding-synchronization-and-data-access-with-system-util-getglobals/86019>\
**Category:** Ignition\
**Tags:** ignition81, scripting\
**Created:** [February 20, 2024, 2:44pm UTC](https://forum.inductiveautomation.com/t/understanding-synchronization-and-data-access-with-system-util-getglobals/86019 "2024-02-20T14:44:55Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![keithms](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/keithms/32/58243_2.png) [@keithms](https://forum.inductiveautomation.com/u/keithms)\
**Post date:** [February 20, 2024, 2:44pm UTC](https://forum.inductiveautomation.com/t/understanding-synchronization-and-data-access-with-system-util-getglobals/86019/1 "2024-02-20T14:44:55Z")

</div>

Hello,

I'm seeking insights on backing storage and synchronization primitives for data accessed via the [system-util-getGlobals function](https://www.docs.inductiveautomation.com/docs/8.1/appendix/scripting-functions/system-util/system-util-getGlobals#keywords). While it seems promising for my goals, I'm looking to better understand its underlying mechanisms to ensure correct implementation.

### Background

I'm more experienced with Rust, so let me share a recent project as context. I had to manage mutable values maintained by their respective tasks running on threads within an asynchronous runtime, with a dedicated TUI thread for visualization. To achieve this, I utilized a `Mutex` as in the following minimal example:

```rust
/// Outer structure wrapping the inner structure in a thread-safe `Mutex`.
struct Data {
    inner: Arc<Mutex<Inner>>,
}

/// Inner structure containing recorded data.
struct Inner {
    values: Vec<u64>,
}

```

I enabled the TUI thread to access the data within a locked scope for its required duration (akin to how I imagine `system.util.getGlobals` could work):

```rust
impl Data {
    /// Access the recorded values inside a closure.
    fn with_values<F, T>(&self, function: F) -> T
    where
        F: FnOnce(&[u64]) -> T,
    {
        let lock = self.inner.lock().expect("acquired mutex guard");
        function(&lock.values)
    }
}

```

### Questions

1. Does the JVM utilize a synchronization primitive similar to Rust's `Mutex` for backing data accessed via `system.util.getGlobals`? Is this synchronization applied to the entire structure or sharded by key?
2. Should Mutex contention be a concern when utilizing `system.util.getGlobals`?
3. Are there scenarios where using `system.util.getGlobals` could potentially lead to deadlocks?

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [February 20, 2024, 2:49pm UTC](https://forum.inductiveautomation.com/t/understanding-synchronization-and-data-access-with-system-util-getglobals/86019/2 "2024-02-20T14:49:08Z")

</div>

It's basically just a ConcurrentMap. It's safe for access by multiple threads in terms of visibility, but there is no mutual exclusion happening.

> **[ConcurrentHashMap (Java SE 17 & JDK 17)](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/ConcurrentHashMap.html)**
>
> declaration: module: java.base, package: java.util.concurrent, class: ConcurrentHashMap

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [February 20, 2024, 2:54pm UTC](https://forum.inductiveautomation.com/t/understanding-synchronization-and-data-access-with-system-util-getglobals/86019/3 "2024-02-20T14:54:50Z")

</div>

1. No. Jython collections, sets, and dictionaries are all based on java "Concurrent" underlying classes, so they are thread-safe, but algorithms built with them are not.

2. Yes. Java is highly multithreaded, so any thread waiting on a mutex could block actions that do not expect to wait (like the tag event thread pool).

3. Not in and of itself, no.

4. (Yeah, you didn't have "4".) The object returned from `system.util.getGlobals()` also holds top-level variables in gateway events. Yes, shared across the entire gateway. Access to those was/is part of its design. I created alternatives (now `system.util.globalVarMap()` in my Integration Toolkit) to avoid this particular complication. (There used to be more problems.)

Careful use of `.setdefault` on Jython dictionaries, and `.putIfAbsent()` on `ConcurrentHashMap`s can reduce the need for mutexes or other locks. Consider this topic:

> [@Using system.util.getGlobals with classes](https://forum.inductiveautomation.com/t/using-system-util-getglobals-with-classes/78760/20):
>
> So, I was nerd-sniped pretty intensely by this yesterday, as the nesting of persistent dictionaries has some performance considerations that suggest some instance caching is appropriate. This is utterly untested, but should give you a framework to use if you decide you really don't want the latency of database storage (and I wouldn't use document tags): from threading import RLock \_g = system.util.getGlobals() # This class requires a dictionary in its constructor to # carry state. It delega…

Related: If you always use one-liners in your gateway events that delegate to project library scripts, then you aren't creating any top-level variables that could clash with other residents of `system.util.getGlobals()`.

---

<div class="post-metadata">

**Author:** ![keithms](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/keithms/32/58243_2.png) [@keithms](https://forum.inductiveautomation.com/u/keithms)\
**Post date:** [February 20, 2024, 3:02pm UTC](https://forum.inductiveautomation.com/t/understanding-synchronization-and-data-access-with-system-util-getglobals/86019/4 "2024-02-20T15:02:02Z")

</div>

I agree on those implementation guidelines.

I thought 4 was implied but I appreciated the added clarification. I think Ignition is a fantastic product but I often see a lot of complicated scripting solutions that quickly go awry as the system they service scales.

I hope that clarifying posts like the ones you both made here and linked to lead to more thoughtful and performant solutions in the future.

Thank you both!

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [February 20, 2024, 3:05pm UTC](https://forum.inductiveautomation.com/t/understanding-synchronization-and-data-access-with-system-util-getglobals/86019/5 "2024-02-20T15:05:29Z")

</div>

You might find this topic helpful, too:

> [@Java concurrent queue for tag change scripts](https://forum.inductiveautomation.com/t/java-concurrent-queue-for-tag-change-scripts/82044):
>
> Continuing the discussion from [[SOLVED] Are tag Value Changed scripts running asynchronously?](https://forum.inductiveautomation.com/t/solved-are-tag-value-changed-scripts-running-asynchronously/68704/5): We've got code in our standard library that I need to log a value change on a tag and then associate various data points with that value change. The value is located in a UDT, and because this is part of our "standard" library we use for our customers, the number of tags is variable and quite possibly numerous so having a gateway tag event script isn't feasible for this solution. I was reading up on …

---

<div class="post-metadata">

**Author:** ![keithms](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/keithms/32/58243_2.png) [@keithms](https://forum.inductiveautomation.com/u/keithms)\
**Post date:** [February 20, 2024, 3:14pm UTC](https://forum.inductiveautomation.com/t/understanding-synchronization-and-data-access-with-system-util-getglobals/86019/6 "2024-02-20T15:14:47Z")

</div>

That link is really great thank you! Also **hard** agree on the point about using bounded channels to handle back pressure. The very same project I mentioned above uses an actor pattern, where an actor holds an IO resource, and its handle passes messages to the actor over a bounded queue. I'm happy to see that this is a pattern I can implement in Ignition as well.
