Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Locking with timeout pattern

lock uses this pattern

if(Monitor.Enter(lock))
    try
    {
        ...
    }
    finally { Monitor.Exit(lock); } // using this style to reduce post "height"

if we don't want to wait infinite we can provide timeout

if(!Monitor.TryEnter(lock, timeout))
    throw new TimeoutException();
try
{
    ...
}
finally { Monitor.Exit(lock); }

I have scenario when method has to obtain multiple locks before it start doing anything. This looks awful:

if(!Monitor.TryEnter(lockA, timeout))
    throw new TimeoutException();
try
{
    if(!Monitor.TryEnter(lockB, timeout))
        throw new TimeoutException();
    try
    {
        if(!Monitor.TryEnter(lockC, timeout))
            throw new TimeoutException();
        try
        {
            ... // more of such constructions
        }
        finally { Monitor.Exit(lockC); }
    }
    finally { Monitor.Exit(lockB); }
}
finally { Monitor.Exit(lockA); }

It has problems:

  • looks ugly (the method code is indented, imagine how it will looks for lockZ), can be solved by putting method code into another method.

  • locking occurs synchronously, so the worst successful case may take time slightly less than a sum of all timeouts.

Is there a way to improve this timeout pattern?

I was thinking to make a method with delegate parameter and lock to achieve something like linq chaining (but to also run locks in parallel, this is a challenge):

Lock(lockA).Lock(lockB).Lock(lockC).Run( () => ...);

Or perhaps there is another way?

like image 895
Sinatr Avatar asked Jun 22 '16 07:06

Sinatr


People also ask

How can I monitor lock timeouts in a database?

You can use the database system monitor to help you track the number of times an application (connection) experienced a lock timeout or that a database detected a timeout situation for all applications that were connected. Too low a value for this configuration parameter. An application (transaction) that is holding locks for an extended period.

What is Semaphore with timeout of lock/unlock operations?

Semaphore pattern implementation with timeout of lock/unlock operations. ? The semaphore provides API to control access to a shared resource by multiple goroutines or limit throughput. releaser, err := semaphore. Acquire ( breaker. BreakByTimeout ( time. Second )) if err != nil { // timeout exceeded } defer releaser. Release ()

What does the lock time parameter do in Java?

This parameter specifies the number of seconds that an application will wait to obtain a lock, helping avoid global deadlocks for applications. If you set this parameter to 0 , locks are not waited for.

What is timeout in microservices design pattern?

Timeout Pattern is one of the simplest Microservice Design Patterns for designing resilient Microservices. Introducing timeout solves the network related issues partially. Not fully.


1 Answers

I would go with usings for sync lock:

using System;
using System.Threading; 

public class MyLock : IDisposable
{
    private object lockObj;

    public MyLock(object lockObj, TimeSpan timeout)
    {
        this.lockObj = lockObj;
        if (!Monitor.TryEnter(this.lockObj, timeout))
            throw new TimeoutException();
    }

    public void Dispose()
    {
        Monitor.Exit(lockObj);
    }
}

Usage:

using(new MyLock(lockA, new TimeSpan.FromSeconds(1)))
using(new MyLock(lockB, new TimeSpan.FromSeconds(2)))
using(new MyLock(lockC, new TimeSpan.FromSeconds(3)))
{
    // your code
}

Do not know if "locking" in ctor is good pattern / design, but it will work ;)

For async. parallelization is not good idea. Why? If some thread will enter the monitor, the same thread must leave it (exit with lock). So if you lock on objA within Parallel.ForEach (f.e.) you will not know which thread has done it. So you won't be able to release it.

like image 86
pwas Avatar answered Sep 23 '22 06:09

pwas