简体   繁体   中英

A lock designed for asynchronous applications

I have a class which has an inner state which can be changed.

These state changes are never simple, and often consist of several asynchronous operations which occur across multiple threads, such as opening a connection and sending some data

By using a lock and a boolean to indicate whether the state is currently changing I can ensure that only one operation can ever have access to the state at any given time

lock (thisLock) {

    while (stateChanging)
        Monitor.Wait(thisLock);


    stateChanging= true;

    //now free to go away and do other things while maintaining exclusive access to the inner state


}

This works fine, but it means there is needless blocking occurring in threads waiting to get exclusive access the state

So what I envision is a lock based on callbacks, where a state changing operation does something like this -

sharedLock.ObtainLock(delegate() {

     //we now have exclusive access to the state
     //do some work

     socket = new Socket();
     socket.BeginConnect(hostname, connectcallback);

});

void connectcallback(IAsyncResult result) {

    socket.EndConnect(result);

    isConnected = true;

    sharedLock.ReleaseLock();


}

Is such a concept common? Does it have a name? Am I approaching things incorrectly?

我最终创建了一个异步信号灯,它确实运行得非常好,而且丝毫没有变态的感觉。

Usually you would use Mutex or Semaphores for this purpose. For example, if a semaphore has just one token and one operation has taken that token, no other operation can be executed until the first operation is finished and the token has been put back to the semaphore.

Within your second code example you just called ObtainLock and ReleaseLock, but then the sharedLock does not know which operation called Obtain/Release. This is why ObtainLock usually returns a token that can either be diposed or released when the operation finished.

IDisposable myLock;

myLock = sharedLock.ObtainLock(delegate() {
     socket = new Socket();
     socket.BeginConnect(hostname, connectcallback);
});

void connectcallback(IAsyncResult result) {
    socket.EndConnect(result);
    isConnected = true;
    myLock.Dispose();
}

The class that implements you sharedLock manages these tokens and according to the state of each token it knows if it's busy or not. Actually nothing more than a reference counter.

As another alternative you might use ManualResetEvent or AutoResetEvents as tokens that you return on ObtainLock. When your operation is finished, just call event.Set()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM