C# 双重检查锁定的可能错误实现
我有一个线程安全类:C# 双重检查锁定的可能错误实现,c#,multithreading,C#,Multithreading,我有一个线程安全类: internal class ExmplFile { private readonly string filename; private int resolution; private volatile PaddedImage gaussian; private object lockObject=new object(); //blah, blah, blah internal PaddedImage Gaussian
internal class ExmplFile
{
private readonly string filename;
private int resolution;
private volatile PaddedImage gaussian;
private object lockObject=new object();
//blah, blah, blah
internal PaddedImage Gaussian()
{
if (gaussian != null)
{
return gaussian;
}
lock (lockObject)
{
if (gaussian == null)
{
Image();
if (File.Exists(filename + "-gaus.raw"))
{
gaussian = LoadImage(filename + "-gaus.raw", TerraGodContext.Instance()
.Config.PpaCandidateRange);
gaussian.ConformRepeatPadding();
}
else
{
gaussian = new PaddedImage(resolution, resolution, false,
TerraGodContext.Instance().Config.PpaCandidateRange);
PaddedImage temp = new PaddedImage(resolution, resolution, false,
TerraGodContext.Instance().Config.PpaCandidateRange);
ImageProcessing.CalcGaussian(image,gaussian,temp, 16f* resolution
/TerraGodContext.Instance().Config.ExmplResDS);
}
}
}
return gaussian;
}
}
Resharper给了我三个警告:
gaussian.com()
中指出可能不正确地实现了双重检查锁定。对选中字段的读取权限。gaussian=new PaddedImage(
它表示可能不正确地执行了双重检查锁定。可能对选中字段进行了多次写入访问。using System;
using System.IO;
using System.Text;
namespace UPlus.TerrEngine
{
internal class ExmplFile : IEquatable<ExmplFile>
{
private readonly string filename;
private int resolution;
private volatile PaddedImage image;
private volatile PaddedImage gaussian;
private object lockObject=new object();
public ExmplFile(string abstractFileName, int res)
{
filename = new StringBuilder(abstractFileName).Append("-").Append(res.ToString("D4")).ToString();
resolution = res;
}
internal FilledList<MatchItem>[] GetMatchItems(int groupIdx, int regionIdx)
{
AlgorithmConfig Config = TerraGodContext.Instance().Config;
if (resolution !=Config.ExmplResDS) throw new Exception();
PpaGraph exmplGraph = new PpaGraph(Config.ExmplResDS, Config.ExmplResDS, Config.ExmplResDS
/ Config.PpaExmplResDS);
exmplGraph.Calculate(Image(), true, false, DebugOpts.BranchMin);
exmplGraph.PrepareGraphForMatch(Config.ExmplCptRadius, Config.ExmplProcNodeDistance);
exmplGraph.CalcExmplProcNodeGroups(groupIdx);
MatchItemFinder matchItemFinder=new MatchItemFinder(Image(),Config.ExmplPatchSizeDS,true);
matchItemFinder.Init(exmplGraph.processNodesGroups, regionIdx);
return matchItemFinder.matchItems;
}
internal FastList<MatchItem> LoadMatchItems()
{
throw new Exception();
}
internal PaddedImage Image()
{
if (image != null)
{
return image;
}
lock (lockObject)
{
if (image == null)
{
image=LoadImage(filename + ".raw", TerraGodContext.Instance().Config
.PpaCandidateRange);
}
}
return image;
}
internal PaddedImage Gaussian()
{
if (gaussian != null)
{
return gaussian;
}
lock (lockObject)
{
if (gaussian == null)
{
Image();
if (File.Exists(filename + "-gaus.raw"))
{
gaussian = LoadImage(filename + "-gaus.raw", TerraGodContext.Instance()
.Config.PpaCandidateRange);
gaussian.ConformRepeatPadding();
}
else
{
gaussian = new PaddedImage(resolution, resolution, false,
TerraGodContext.Instance().Config.PpaCandidateRange);
PaddedImage temp = new PaddedImage(resolution, resolution, false,
TerraGodContext.Instance().Config.PpaCandidateRange);
ImageProcessing.CalcGaussian(image,gaussian,temp, 16f* resolution
/TerraGodContext.Instance().Config.ExmplResDS);
}
}
}
return gaussian;
}
private PaddedImage LoadImage(string fileName, int padding)
{
PaddedImage img=new PaddedImage(resolution,resolution,false,padding);
img.LoadRaw(fileName);
img.ConformRepeatPadding();
return img;
}
public bool Equals(ExmplFile other)
{
return filename == other.filename;
}
public override int GetHashCode()
{
return filename.GetHashCode();
}
}
}
使用系统;
使用System.IO;
使用系统文本;
命名空间UPlus.TerrEngine
{
内部类ExmplFile:IEquatable
{
私有只读字符串文件名;
私有整数分解;
私有图像;
私有易失性paddiedimage高斯;
私有对象lockObject=新对象();
公共ExmplFile(字符串抽象文件名,int-res)
{
filename=新的StringBuilder(abstractFileName).Append(“-”).Append(res.ToString(“D4”)).ToString();
分辨率=分辨率;
}
内部填充列表[]GetMatchItems(int-groupIdx,int-regionIdx)
{
AlgorithmConfig Config=TerraGodContext.Instance().Config;
if(resolution!=Config.ExmplResDS)抛出新异常();
PpaGraph exmplGraph=新的PpaGraph(Config.ExmplResDS,Config.ExmplResDS,Config.ExmplResDS
/Config.ppaexplresds);
计算(Image(),true,false,DebugOpts.BranchMin);
PrepareGraphForMatch(Config.ExmplCptRadius,Config.exmplprocNodeInstance);
exmplGraph.CalcExmplProcNodeGroups(groupIdx);
MatchItemFinder MatchItemFinder=新的MatchItemFinder(Image(),Config.ExmplPatchSizeDS,true);
matchItemFinder.Init(exmplGraph.processNodesGroups,regionIdx);
返回matchItemFinder.matchItems;
}
内部FastList LoadMatchItems()
{
抛出新异常();
}
内部PaddeImage图像()
{
如果(图像!=null)
{
返回图像;
}
锁定(锁定对象)
{
if(image==null)
{
image=LoadImage(文件名+“.raw”,TerraGodContext.Instance().Config
(b)特兰奇(e);;
}
}
返回图像;
}
内部填充图像高斯()
{
if(高斯!=null)
{
返回高斯分布;
}
锁定(锁定对象)
{
如果(高斯==null)
{
图像();
如果(File.Exists(filename+“-gaus.raw”))
{
gaussian=LoadImage(文件名+“-gauss.raw”,TerraGodContext.Instance()
.Config.ppatarange);
gaussian.padding();
}
其他的
{
高斯=新的填充图像(分辨率、分辨率、假、,
TerraGodContext.Instance().Config.PpaCandidateRange);
PaddedImage temp=新的PaddedImage(分辨率、分辨率、假、,
TerraGodContext.Instance().Config.PpaCandidateRange);
图像处理.CalcGaussian(图像,高斯,温度,16f*分辨率
/TerraGodContext.Instance().Config.ExmplResDS);
}
}
}
返回高斯分布;
}
私有PaddedImage LoadImage(字符串文件名,整数填充)
{
PaddedImage img=新的PaddedImage(分辨率、分辨率、假、填充);
LoadRaw(文件名);
img.padding();
返回img;
}
公共布尔等于(ExmplFile其他)
{
返回filename==other.filename;
}
公共覆盖int GetHashCode()
{
返回filename.GetHashCode();
}
}
}
编辑:如果情况不清楚,这里有一个屏幕截图:
尝试使用来定义您的属性。您的代码看起来正确,但这应该可以消除错误,这是一种适用于此类事情的框架模式尝试使用来定义您的属性。您的代码看起来正确,但应该可以消除错误,并且是适用于此类事情的框架模式T你的锁有点奇怪。我在静态锁对象而不是私有对象上见过它。
如果你的类不是singleton,那么你的锁就会通过,因为没有锁。你的锁有点奇怪。我在静态锁对象而不是私有对象上见过它。
如果您的类不是单例的,那么您的锁将通过,因为没有锁。通常,在
锁中,您应该使用局部变量,并将对选中字段的写入作为最后一个可能的操作
另外,你在中间做什么?例如<代码>构象重复pAdvices()/代码>?我猜它有副作用,因为它没有返回值。但是在你调用它的时候,你已经通过将它的值分配给该字段来暴露该对象。
其他线程可能能够以“部分构造”的方式观察此对象说明如果过早分配给字段,如我所说,通常应使写入字段成为锁中最后一个可能的操作通常,在锁中,应使用局部变量并使写入选中字段成为最后一个可能的操作
另外,你在中间做什么?例如<代码>构象重复pAdv>代码>?我猜它是有边的。