What I need to achieve is:
(Link to used AsyncLock).
private async Task MasterAsync()
{
using (await _asyncLock.LockAsync())
{
await Task.Delay(2000);
}
}
private async Task HumbleSlave1Async()
{
using (await _asyncLock.LockAsync())
{
await Task.Delay(5000);
}
}
private async Task HumbleSlave2Async()
{
using (await _asyncLock.LockAsync())
{
await Task.Delay(5000);
}
}
I am not sure how to solve it, was thinking about use of two different locks for each slave in MasterAsync but then one lock would be in another:
private async Task MasterAsync()
{
using (await _asyncLock1.LockAsync())
{
using (await _asyncLock2.LockAsync())
{
await Task.Delay(2000);
}
}
}
private async Task HumbleSlave1Async()
{
using (await _asyncLock1.LockAsync())
{
await Task.Delay(5000);
}
}
private async Task HumbleSlave2Async()
{
using (await _asyncLock2.LockAsync())
{
await Task.Delay(5000);
}
}
Does it make sense and is it safe(deadlocks, etc...) especially when I used AsyncLock ?
When MasterAsync is executing, HumbleSlave1Async and HumbleSlave2Async can NOT. Vice Versa- When one or both of Slaves are executing, MasterAsync can NOT. Difficult part- Slaves can NOT block each other.
First, double-check whether you really want this. The majority of the time, a restructuring of the code responsibilities will simplify what synchronization you need (and is usually more efficient, too).
That said, your scenario fits a reader/writer lock. A RWL is a lock that can be taken two different ways, as a "writer" (which does not allow any other locks at the same time) or as a "reader" (which allows other readers but not writers). Stephen Toub has an async
-compatible one here and I have one as part of my AsyncEx library.
Update: Example code:
private readonly AsyncReaderWriterLock _lock = new AsyncReaderWriterLock();
private async Task MasterAsync()
{
using (await _lock.WriterLockAsync())
{
await Task.Delay(2000);
}
}
private async Task HumbleSlave1Async()
{
using (await _lock.ReaderLockAsync())
{
await Task.Delay(5000);
}
}
private async Task HumbleSlave2Async()
{
using (await _lock.ReaderLockAsync())
{
await Task.Delay(5000);
}
}
A possible problem with your approach is that when HumbleSlave2Async
is executing, and MasterAsync
has been called, acquired asyncLock1
and is awaiting asyncLock2
, you won't be able to execute HumbleSlave1Async
(because asyncLock1
is taken by MasterAsync
). So, your condition #3 will not be satisfied.
Maybe you should use something like AsyncManualResetEvent to make this work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With