如何通过使用Lock和委托来同步方法访问(线程安全) [英] How to synchronize method access(thread safe) by using Lock and delegates
问题描述
假设我们有一个像这样的方法
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 delegate
s 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
.Lock
或Mutex
更快吗?
- How to avoid
Deadlock
and release lock after a specific timeout? Mutex
is similar toLock
in some aspects.isLock
orMutex
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
如您所见,lock
比mutex
如何确定代码的共享资源部分?
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屋!