@Override
    public Difference<Node> remove(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;
            }

            // remove any nodes that match, record to results
            removeMatching(nodes.iterator(), node, result);

            // update inheritance map too
            if (node instanceof InheritanceNode) {
                SortedSet<InheritanceNode> inhNodes = this.inheritanceMap.get(context);
                if (inhNodes != null) {
                    inhNodes.removeIf(el -> node.equals(el, NodeEqualityPredicate.IGNORE_EXPIRY_TIME_AND_VALUE));
                }
            }

        } 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