这是一些简单的代码,演示了我正在尝试做什么
myVar = 1
reader = () ->
getDataFromServer1().then ->
# uses myVar and does stuff according to its value
# returns promise
writer = () ->
getDataFromServer2().then ->
# assigns to myVar
# returns promise
Q.all([reader(), reader(), reader(), writer(), writer(), writer()]).done ->
console.log 'done'
所以我有多个线程同时运行。其中一些更改myVar
的值,有些读取值并依赖它。当另一位作家正在写作或读者正在阅读时,我不希望作家写作。读者可以同时阅读。这类似于Readers–writers problem。
我尝试通过定义sharedResource
函数来解决此问题,如下所示
sharedResource = (initialValue) ->
readLock = Q.fcall ->
writeLock = Q.fcall ->
value: initialValue
read: (action) ->
newPromise = writeLock.then action
readLock = Q.all([newPromise, readLock]).then -> null
newPromise
write: (action) ->
newPromise = Q.all([readLock, writeLock]).then action
writeLock = Q.all([newPromise, writeLock]).then -> null
newPromise
然后更改了我的代码以使用它
myVar = sharedResource 1
reader = () ->
myVar.read ->
# noone is writing to myVar while doing this request:
getDataFromServer1().then (data) ->
# read myVar.value instead of myVar, e.g.
expect(data == myVar.value)
writer = () ->
myVar.write ->
# noone reads or writes myVar while doing this request:
getDataFromServer2().then (data) ->
# change myVar.value instead of myVar, e.g.
myVar.value = data
Q.all([reader(), reader(), reader(), writer(), writer(), writer()]).done ->
console.log 'done'
当我只有一个sharedResource
时,这非常有效。这是问题发生的地方
myVar1 = sharedResource 1
myVar2 = sharedResource 2
action1 = () ->
myVar1.read ->
myVar2.write ->
getDataFromServer1().then (data) ->
myVar2.value = data + myVar1.value
action2 = () ->
myVar2.read ->
myvar1.write ->
getDataFromServer2().then (data) ->
myVar1.value = data + myVar2.value
Q.all([action1(), action1(), action1(), action2(), action2(), action2()]).done ->
console.log 'done'
这里发生deadlock的案例。每个承诺都在等待另一个人解决。他们都没有得到解决,程序也停止了。
修改
我会尽力解释:
这实际上是测试我的服务器的代码。查看多个客户端同时发送多个请求时的执行情况。比如说每次action1
发送请求时,服务器都会增加存储在其数据库中的值。在客户端(您看到的代码),我还增加一个变量,其中包含我期望在服务器上的值。然后当action2
发送请求时,服务器以该值响应,并且assert
响应中的值与我的本地变量相同。
所以我必须在发送请求之前获取锁定,以确保action2
在更改变量时不会要求变量。
我希望有所帮助。