@Override
    public Difference<Node> removeExact(Node node) {
        ImmutableContextSet context = node.getContexts();
        Difference<Node> result = new Difference<>();

        this.lock.lock();
        try {
            SortedSet<Node> nodes = this.map.get(context);
            if (nodes == null) {
                return result;
            }

            // try to remove an exact match
            if (nodes.remove(node)) {
                // if we removed something, record to results
                result.recordChange(ChangeType.REMOVE, node);

                // update inheritance map too if necessary
                if (node instanceof InheritanceNode && node.getValue()) {
                    SortedSet<InheritanceNode> inhNodes = this.inheritanceMap.get(context);
                    if (inhNodes != null) {
                        inhNodes.remove(node);
                    }
                }
            }

        } finally {
            this.lock.unlock();
        }

        return result;
    }
This lock is used whilst performing mutations, but *not* reads.

The maps themselves are thread safe, so for querying, we just allow
the read methods to do whatever they want without any locking.
However, we want mutations to be atomic, so we use the lock to ensure that happens.
common/src/main/java/me/lucko/luckperms/common/model/nodemap/NodeMapMutable.java