同步访问共享资源以异步调用 Spring Web 服务器似乎不适用于 @Synchronized

Synchronising access to a shared resource for asynchronous calls to a Spring Webserver does not seem to work with @Synchronized

我有一个 SpringBoot 网络服务器;在它上面,一个操纵单例实例状态的路由。此路由通常由多个参与者调用,因此必须同步。

路由调用对应的方法,是set():

@Synchronized
public fun <T> set(t: T) {
    val incomingState = State.from(t)
    if(incomingState == innerState){
        return
    }
    change(incomingState)
}

@Synchronized
private fun change(newState: State){
    this.stateAccessLock.lock()
    SystemLog.logResourceLocking("HomeState", isLocked = true)
    SystemLog.logHomeEvent("Changing HomeState from '${innerState.name}' to '${newState.name}'")
    try {
        Home.INSTANCE.EXTENSION.broadcastStateChange(
            innerState?.name,
            newState.name
        )
    }
    finally {
        innerState = newState
        Home.save()

        stateAccessLock.unlock()
        SystemLog.logResourceLocking("HomeState", isLocked = false)
    }
}

在使用@Synchronized注解之前,我也尝试过在同一个class中使用ReentrantLock (如您所见,到目前为止我都忽略了删除它)。初始化如下:

private var stateAccessLock = ReentrantLock()

@Autowired
fun HomeState(@Qualifier("stateAccessLock") stateAccessLock: ReentrantLock) {
    this.stateAccessLock = stateAccessLock
}

现在,change() 中的第三行和最后一行记录资源被锁定并免费提供。过滤这些事件的日志文件给我这个:

[2020-10-09T16:07:01.709]       LOCK: Resource locked
[2020-10-09T16:07:01.710]       LOCK: Resource locked
[2020-10-09T16:07:01.725]       LOCK: Resource locked
[2020-10-09T16:07:01.727]       LOCK: Resource locked
[2020-10-09T16:07:01.818]       LOCK: Resource unlocked
[2020-10-09T16:07:01.828]       LOCK: Resource unlocked
[2020-10-09T16:07:01.829]       LOCK: Resource unlocked
[2020-10-09T16:07:01.839]       LOCK: Resource unlocked
[2020-10-09T16:11:33.499]       LOCK: Resource locked
[2020-10-09T16:11:33.523]       LOCK: Resource locked
[2020-10-09T16:11:33.525]       LOCK: Resource locked
[2020-10-09T16:11:33.692]       LOCK: Resource unlocked
[2020-10-09T16:11:33.692]       LOCK: Resource unlocked
[2020-10-09T16:11:33.693]       LOCK: Resource unlocked
[2020-10-09T16:11:35.881]       LOCK: Resource locked
[2020-10-09T16:11:35.959]       LOCK: Resource unlocked

显然,我想要这样的东西:

[2020-10-09T16:07:01.709]       LOCK: Resource locked
[2020-10-09T16:07:01.710]       LOCK: Resource unlocked
[2020-10-09T16:07:01.725]       LOCK: Resource locked
[2020-10-09T16:07:01.727]       LOCK: Resource unlocked
[2020-10-09T16:07:01.818]       LOCK: Resource locked
[2020-10-09T16:07:01.828]       LOCK: Resource unlocked
[2020-10-09T16:07:01.829]       LOCK: Resource locked
[2020-10-09T16:07:01.839]       LOCK: Resource unlocked

我错过了什么? 提前致谢!

由于您没有return 从这些方法中得到任何东西,所以我会改用线程限制并完全放弃锁定。这也将确保您不会陷入僵局:

private val executor = Executors.newSingleThreadExecutor()

fun <T> set(t: T) {
    executor.submit {
        val incomingState = State.from(t)
        if (incomingState == innerState) {
            return
        }
        change(incomingState)
    }
}

因为你有一个 single-threaded 执行器,你可以确保请求以串行方式处理(并且没有锁定)。