如何在多线程环境中只执行一次代码块?
Posted
技术标签:
【中文标题】如何在多线程环境中只执行一次代码块?【英文标题】:How to execute a block of code only once on a multithreading environment? 【发布时间】:2021-11-25 23:22:16 【问题描述】:以下代码块在 C# 中执行对象的加载。
public bool IsModelLoaded get; set;
public override MyObject Load()
if (!IsModelLoaded)
Model = MyService.LoadMyObject(Model);
IsModelLoaded = true;
return Model;
我的意图是只运行一次这个块,因此只加载一次Model
。然而,这个代码块从 2 个不同的线程运行了两次。
如何确保此块只运行一次? (在多个线程上)。
【问题讨论】:
【参考方案1】:使用Lazy<T> Class:
private readonly Lazy<MyObject> myObject;
public MyClass()
myObject = new Lazy<MyObject>(() =>
return MyService.LoadMyObject();
, LazyThreadSafetyMode.ExecutionAndPublication);
public bool IsModelLoaded
get return myObject.IsValueCreated;
public override MyObject Load()
return myObject.Value;
【讨论】:
【参考方案2】:最简单的就是添加
[MethodImpl(MethodImplOptions.Synchronized)]
public override MyObject Load()
//snip
但请注意,这会锁定整个对象,而不仅仅是方法。不是很好的做法。
http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.methodimploptions.aspx
同步
指定该方法一次只能由一个线程执行。静态方法锁定类型,而实例方法锁定实例。任何实例函数中只能有一个线程执行,类的任何静态函数中只能有一个线程执行。
【讨论】:
【参考方案3】:我正在尝试实现singleton
模式。但是您的版本不是线程安全的。在此处阅读更多信息:http://www.dofactory.com/Patterns/PatternSingleton.aspx。尝试使用此实现:
public sealed class Singleton
static Singleton instance=null;
static readonly object padlock = new object();
Singleton()
public static Singleton Instance
get
lock (padlock)
if (instance==null)
instance = new Singleton();
return instance;
【讨论】:
【参考方案4】:如果你想编写线程安全的代码并确保块只运行一次,你可以这样写:
private System.Object lockThis = new System.Object();
public override MyObject Load()
lock (lockThis)
if (!IsModelLoaded)
Model = MyService.LoadMyObject(Model);
IsModelLoaded = true;
return Model;
【讨论】:
【参考方案5】:Action myCodeBlock = ()=>
//do your job
//...
myCodeBlock = ()=>;
在调用myCodeBlock()
一次后,它将被什么都不做的方法重写。您仍然需要确保安全地调用此方法 - 使用 lock
或其他。
【讨论】:
【参考方案6】:您可以使用lock Statement (C# Reference)
【讨论】:
【参考方案7】:创建一个静态对象(如布尔值),通过将其放入 if 语句中来确定代码是否已运行 :)
编辑:我不确定这是否是线程安全的,所以它可能不是你的解决方案。
【讨论】:
以上是关于如何在多线程环境中只执行一次代码块?的主要内容,如果未能解决你的问题,请参考以下文章