我有一个线程安全类:
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.ConformRepeatPadding()
的高斯上,它表示 可能错误地实现了双重检查锁定。对已检查字段的读访问权。 。gaussian = new PaddedImage(
的高斯上,它表示 可能错误地实现了双重检查锁定。可能对已检查字段进行多次写访问。 。ImageProcessing.CalcGaussian(image,gaussian,temp,
的高斯上,它表示 可能错误地实现了双重检查锁定。读取对已检查字段的访问权限。 (与编号1相同的警告)。我是傻还是Resharper?
PS:如果我错过了一些重要内容,这里是完整的类代码,上面省略了部分内容。
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();
}
}
}
编辑:以下是情况不明确的截图:
答案 0 :(得分:2)
尝试使用Lazy<T>来定义您的媒体资源。你的代码看起来是正确的,但这应该摆脱错误,并且是一种框架模式,正是这种事情
答案 1 :(得分:2)
通常,在lock
内,您应该使用局部变量并对已检查字段进行 last 可能的操作。
否则,你在中间做什么?例如。 ConformRepeatPadding()
做了什么?我猜它有副作用,因为它没有返回值?但是当你调用它时,你已经已经通过将该值赋给该字段来公开该对象。
如果您过早地分配给该字段,其他线程可能能够以“部分构造”状态观察此对象,因此我应该通常在{{{{{{{{{ 1}}。
答案 2 :(得分:0)
你的锁有些奇怪。我已经在静态锁定对象上看到了它,而不是私有对象。 如果你的班级不是单身,那么你的锁定就会通过,因为没有锁定。