nodejs读者/作者并发

时间:2014-11-05 11:46:33

标签: node.js coffeescript promise deadlock q

这是一些简单的代码,演示了我正在尝试做什么

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在更改变量时不会要求变量。

我希望有所帮助。

0 个答案:

没有答案