同步访问共享资源以异步调用 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 执行器,你可以确保请求以串行方式处理(并且没有锁定)。
我有一个 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 执行器,你可以确保请求以串行方式处理(并且没有锁定)。