如何通过使用Lock和委托来同步方法访问(线程安全) [英] How to synchronize method access(thread safe) by using Lock and delegates

查看:87
本文介绍了如何通过使用Lock和委托来同步方法访问(线程安全)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有一个像这样的方法

Assume we have a method like this

public static void method(string param)
{
    ** critical section **
    // There are a lot of methods calls 
    // switch cases 
    // if conditions 
    // read and write in dictionary 
    // new class initiations
    ** critical section **  
}

如何在发生数千个并发调用的同时将其设置为thread-safe?

how we can make it thread-safe while thousand of concurrent calls happen?

可以帮忙吗?我在此处读到

Modify事件不是线程安全的,但是调用委托是 线程安全的.由于Delegate是不可变的类型,因此它是线程安全的.

Modifying event is not thread-safe, but invoking a Delegate is thread-safe. Since a Delegate is immutable type so it is thread safe.

这是否意味着delegate将我的代码设置为thread-safe?

Does that mean that delegates make my code thread-safe?

如果delegate没有授予thread-safe并发呼叫.你能解释为什么吗?

If delegate doesn’t grantee thread-safe concurrent calls. Can you explain why?

如果Lock受赠方thread-safe照原样进行,则:

If Lock grantee thread-safe as it is for then:

  • 如何避免Deadlock并在特定超时后释放锁定?
  • Mutex在某些方面类似于Lock.LockMutex更快吗?
  • How to avoid Deadlock and release lock after a specific timeout?
  • Mutex is similar to Lock in some aspects.is Lock or Mutex faster?

为了更好地调整性能,Dose Visual Studio能够分析共享资源的位置?

For better performance tuning, Dose Visual Studio have the ability to analyze where shared resources are?

推荐答案

Lock或Mutex更快吗?

Is Lock or Mutex faster?

using System;
using System.Diagnostics;
using System.Threading;

namespace LockingTest
{
    class Program
    {
        public static object locker = new object();
        public static Mutex mutex = new Mutex();
        public static ManualResetEvent manualResetEvent = new ManualResetEvent(false);
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            sw.Restart();
            for (int i = 0; i < 10000000; i++)
            {
                mutex.WaitOne(); // we are testing mutex time overhead
                mutex.ReleaseMutex();
            }
            sw.Stop();
            Console.WriteLine("Mutex :" + "  proccess time token " + sw.Elapsed.ToString() + " miliseconds");
            Thread.Sleep(1000); // let os to be idle 
            sw.Restart();
            for (int i = 0; i < 10000000; i++)
            {
                lock (locker) { } // we are testing lock time overhead
            }
            sw.Stop();
            Console.WriteLine("Lock :" + "  proccess time token " + sw.Elapsed.ToString() + " miliseconds");           
            Console.ReadLine();
        }
    }
}

如果您将以上代码复制并粘贴到visual stuido中并运行它,您将看到

if you copy and paste above code in visual stuido and run it you will see

如您所见,lockmutex

如何确定代码的共享资源部分?

How is the shared resource part of the code determined?

为了更好地调整性能,Dose Visual Studio能够分析共享资源的位置?

For better performance tuning, Dose Visual Studio have the ability to analyze where shared resources are?

在Visual Studio 2015中,我已将Visual Studio 2010 更新为 2015 ,当您查看每种方法的顶部时,会看到引用看下面的图像. >

i have updated my visual studio 2010 to 2015,in visual studio 2015, when you look top of each method you will see references look below image. >

当对方法的引用增加时,内存损坏的危险就会增加,反之亦然.

When references to a method goes high the danger of memory corruption goes high and vise versa.

如何避免死锁并在特定超时后释放锁

How to avoid Deadlock and release lock after a specific timeout

using System;
    using System.Diagnostics;
    using System.Threading;
    using System.Threading.Tasks;
    namespace LockReleaseTest
    {
        class Program
        {
            public static object locker = new object();
            public static ManualResetEvent mre = new ManualResetEvent(false);
            public static bool isWorkDone = false;
            public class StateObject
            {
                public int ThreadNumber;
                public string Criticla_Parameter;
                public int ItTakes = 1000;
            }
            static void Main(string[] args)
            {
                for (int i = 0; i < 5; i++)
                {
                    StateObject state = new StateObject();
                    state.ThreadNumber = i;
                    state.Criticla_Parameter = "critical " + i.ToString();
                    ThreadPool.QueueUserWorkItem(method, state);
                }
                Thread.Sleep(13000); // wait previous process to be done
                Console.WriteLine("In order to test release lock after 2.5 sec press enter");
                Console.ReadLine();
                for (int i = 0; i < 5; i++)
                {
                    StateObject state = new StateObject();
                    state.ThreadNumber = i;
                    state.ItTakes = (i + 1) * (1000);
                    state.Criticla_Parameter = "critical " + i.ToString();
                    ThreadPool.QueueUserWorkItem(method2, state);
                }
                Console.ReadLine();
            }
            public static void method(Object state)
            {
                lock (locker)
                {
                    // critcal section
                    string result = ((StateObject)state).Criticla_Parameter;
                    int ThreadNumber = ((StateObject)state).ThreadNumber;
                    Console.WriteLine("Thread " + ThreadNumber.ToString() + " entered");
                    // simultation of process            
                    Thread.Sleep(2000);
                    Console.WriteLine("ThreadNumber is " + ThreadNumber + " Result of proccess : " + result);
                    // critcal section
                }
            }
            public static void method2(Object state)
            {
                if (Monitor.TryEnter(locker, -1))
                {
                    mre.Reset();
                    ThreadPool.QueueUserWorkItem(criticalWork, state);
                    Thread.Sleep(200);
                    ThreadPool.QueueUserWorkItem(LockReleaser, ((StateObject)state).ThreadNumber);
                    mre.WaitOne();
                    Monitor.Exit(locker);
                }
            }
            public static void criticalWork(Object state)
            {
                isWorkDone = false;
                string result = ((StateObject)state).Criticla_Parameter;
                int ThreadNumber = ((StateObject)state).ThreadNumber;
                int HowMuchItTake = ((StateObject)state).ItTakes;
                // critcal section
                Console.WriteLine("Thread " + ThreadNumber.ToString() + " entered");
                // simultation of process            
                Thread.Sleep(HowMuchItTake);
                Console.WriteLine("ThreadNumber " + ThreadNumber + " work done. critical parameter is : " + result);
                isWorkDone = true;
                mre.Set();
                // critcal section
            }
            public static void LockReleaser(Object ThreadNumber)
            {
                Stopwatch sw = new Stopwatch();
                sw.Restart();
                do
                {
                    if (isWorkDone) return; // when work is done don't release lock // continue normal
                } while (sw.Elapsed.Seconds <= 2.5); // timer in order to release lock
                if (!isWorkDone) // more than 2.5 sec time took but work was not done
                {
                    Console.WriteLine("ThreadNumber " + ThreadNumber + " work NOT done. Lock must be released ");
                    mre.Set();
                }
            }
        }
    }

如果您将以上代码复制并粘贴到Visual Studio中并运行,您将获得如下所示的结果

If you copy and paste the above code in visual studio and run it you will get a result looks like this

如您所见,在第一个进程中,我们不释放锁,并且所有线程都按顺序进入临界区,但是在第二个进程中,当进程经过很长时间并且下一个线程被释放时,我们确实释放了锁(线程2)进入并获取锁. 因为必须在父线程中释放该锁,所以我们使用ManualEventRest来指示父级释放该锁.我尝试了其他方法,但是它们没有用,并且发生了SynchronizationLockException异常.这是我发现的没有抛出异常的最佳方法.

As you can see ,in the first processes we do not release lock and all the threads enters sequentially to critical section but in the second process we do release the lock when process goes long time and when the lock is released next thread(Thread 2) enters and acquires the lock. Because, the lock must be released in parent thread then we use ManualEventRest to signal the parent to release the lock. i tried other approaches but they didn't work and exception of SynchronizationLockException happens .This is the best approach that i found without throwing exception.

如果此帖子有用,请别忘了投票.真诚的感谢您

If this post is useful don't forget to vote up.sincerely yours

这篇关于如何通过使用Lock和委托来同步方法访问(线程安全)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆