这样使用本地引用似乎没有问题。我写了以下课程:
public class DataHolder
{
public int Id { get; set; }
public string Name { get; set; }
public static DataHolder InitRandom()
{
var random = new Random();
return new DataHolder() {Id = random.Next(), Name = random.Next().ToString()};
}
}
public class OneThread
{
public static readonly OneThread Instance = new OneThread();
public OneThread()
{
Data = DataHolder.InitRandom();
}
public DataHolder Data;
// this method is called often by one thread
public void RunsEverySecond()
{
Data = DataHolder.InitRandom();
}
}
public class MultiThread
{
public static List<string> Results = new List<string>();
// called externaly by multiple threads
public static bool SomeMethod()
{
var loc = OneThread.Instance.Data;
// initializing new Random every time on purpose since that also takes time
Thread.Sleep(new Random().Next(0,3));
var id = loc.Id;
var name = loc.Name;
var res = loc.Id == id && loc.Name == name;
if (!res)
throw new Exception("different");
var log = String.Format("{0} - OneThreadId: {1}, loc.Id: {2}, id: {3}", res, OneThread.Instance.Data.Id,
loc.Id, id);
lock (Results)
{
Results.Add(log);
}
return res;
}
public static void SpitResults()
{
File.WriteAllLines("C:\\res.txt", Results);
}
}
为了测试,我创建了带有两个按钮的窗口窗体应用程序,用于初始化类并调用它们:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
_secondTimer = new Timer(state => OneThread.Instance.RunsEverySecond(), null, 0, 2);
}
private Timer _secondTimer;
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 10000; i++)
{
ThreadPool.QueueUserWorkItem(o => MultiThread.SomeMethod());
}
}
private void button2_Click(object sender, EventArgs e)
{
MultiThread.SpitResults();
}
}
多次运行此测试后,我得到以下结果:
True - OneThreadId: 968900563, loc.Id: 968900563, id: 968900563
True - OneThreadId: 968900563, loc.Id: 968900563, id: 968900563
True - OneThreadId: 1739428491, loc.Id: 968900563, id: 968900563
True - OneThreadId: 1739428491, loc.Id: 968900563, id: 968900563
True - OneThreadId: 1739428491, loc.Id: 968900563, id: 968900563
True - OneThreadId: 1739428491, loc.Id: 968900563, id: 968900563
True - OneThreadId: 1739428491, loc.Id: 968900563, id: 968900563
True - OneThreadId: 1739428491, loc.Id: 1739428491, id: 1739428491
True - OneThreadId: 1739428491, loc.Id: 1739428491, id: 1739428491
True - OneThreadId: 1739428491, loc.Id: 968900563, id: 968900563
所以,我的结论是,在这种情况下根本不需要主动锁定,如果我将类字段“复制”到局部变量,就不会有任何问题 - 那里的值不会改变,可以放心使用.
如果您发现我的发现有任何错误,请发表评论/随时编辑。