hekailiang / squirrel

squirrel-foundation is a State Machine library, which provided a lightweight, easy use, type safe and programmable state machine implementation for Java.
http://hekailiang.github.io/squirrel/
Other
2.19k stars 540 forks source link

ActionsImpl getSortedAction 方法会触发并发问题 #145

Open Angry-Rabbit opened 10 months ago

Angry-Rabbit commented 10 months ago

多线程首次执行状态机时,会出现并发问题

原来代码:

`

@Override
public List<Action<T, S, E, C>> getAll() {
    return getSortedAction();
}

private List<Action<T, S, E, C>> getSortedAction() {
    if(actions.isEmpty()) 
        return Collections.emptyList();

    if(sortedActions==null) {
        //问题1 这里多个线程同时能进来,
        sortedActions = Lists.newArrayList(actions);   // 问题2 提前的赋值会造成其它线程提早拿到一个未排序的actions
        Collections.sort(sortedActions, new Comparator<Action<T, S, E, C>>() {  // 问题3 Collections.sort会影响sortedActions这个共有集合的可操作性,进而引发异常
            @Override
            public int compare(Action<T, S, E, C> o1, Action<T, S, E, C> o2) {
                return o2.weight() - o1.weight();
            }
        });
        sortedActions = Collections.unmodifiableList(sortedActions);
    }
    return sortedActions;
}`

因我idea连接不上github所以, 解决的代码粘在下面给作者参考:

`

@Override
public List<Action<T, S, E, C>> getAll() {
    return sortedActions != null ? sortedActions : getSortedAction();
}

private synchronized List<Action<T, S, E, C>> getSortedAction() {
    if (sortedActions != null) {
        return sortedActions;
    }

    if (!actions.isEmpty()) {
        List<Action<T, S, E, C>> tmpActions = Lists.newArrayList(this.actions);
        Collections.sort(tmpActions, (o1, o2) -> o2.weight() - o1.weight());
        sortedActions = Collections.unmodifiableList(tmpActions);
    } else {
        sortedActions = Collections.emptyList();
    }
    return sortedActions;
}`
huan670119408 commented 3 months ago

正解,初次执行时,并发情况下 可能会抛ConcurrentModificationException异常