可能重复:
为什么锁(这个){...}不好?
在C#中使关键区域线程安全,我们可以使用lock()语句.lock语句接受一个对象.如果我们传递this给lock语句有什么问题?
我正在尝试编写一个多线程程序,其中每个线程将使用一个计数器,然后递增它.
例如:
lock(this)
{
counter++;
Console.WriteLine(counter);
}
Run Code Online (Sandbox Code Playgroud)
我知道,对于增量我可以使用:
System.Threading.Interlocked.Increment(counter);
Run Code Online (Sandbox Code Playgroud)
但是如果锁定增量和对计数器做某事呢?
谢谢!
鉴于,
private object _x;
private object LoadAndSet(ref object x) {
// lock established over read and update
lock (somePrivateObjectNotUsedElsewhereThatIsIrrelvantToTheQuestion) {
if (x == null)
x = Load();
return x;
}
}
Run Code Online (Sandbox Code Playgroud)
调用为,
public object Load() {
return LoadAndSet(ref _x);
}
Run Code Online (Sandbox Code Playgroud)
_xlock也就是说,第一个代码等价于下面直接使用字段的地方吗?(赋值直接发生,而不是通过ref参数。)
private object _x;
private object LoadAndSetFieldDirectly() {
// lock established over read and update
lock (somePrivateObjectNotUsedElsewhereThatIsIrrelvantToTheQuestion) {
if (_x == null)
_x = Load();
return _x;
}
} …Run Code Online (Sandbox Code Playgroud) 我可以lock非静态方式使用对象吗?另一方面,此代码是线程安全的吗?
static readonly object _object = new object();
public void Get()
{
lock (_object)
{
...
}
}
Run Code Online (Sandbox Code Playgroud) 我试图通过为一些非常核心的函数引入缓存层来从我的数据库服务器卸载工作,这些函数将值插入数据库中的表并检索id.这是一个多线程环境.
我的第一个方法是:
public class Cache {
private Dictionary<string, Int64> i;
public void Init() { /* init i with values from DB */ }
public Int64 Get(string value)
lock(i) {
Int64 id;
if (cache.i.TryGetValue(value, out id))
return id;
id = /* Insert to DB and retrieve ID */
cache.i[value] = id;
return id;
}
}
Run Code Online (Sandbox Code Playgroud)
这有帮助.然而,线程仍然相互等待很多.我想减少这个等待时间.我的第一个想法是使用ConcurrentDictionary.GetOrAdd(key, valueFactory).这不起作用,因为可以多次调用valueFactory.
我已经结束了这种方法:
public class Cache
{
private ConcurrentDictionary<string, Int64> i;
public void Init() { /* init i with values from DB */ } …Run Code Online (Sandbox Code Playgroud) 我想知道你如何知道何时锁定整个类型
lock (typeof(MyClass))
{
...
}
Run Code Online (Sandbox Code Playgroud)
或一个实例
lock (this)
{
...
}
Run Code Online (Sandbox Code Playgroud)
或一个物体
lock (this._lockObj)
{
...
}
Run Code Online (Sandbox Code Playgroud)
我问这个问题是因为我有一个静态类,它是 Enterprise Library 5 的简单包装器,并且可由多个组件从可能不同的线程访问。WriteLog() 方法被锁定。我用的是type来锁的。
我看到了很多:
object lockObj;
List<string> myStrs;
// ...
lock(lockObj)
{
myStrs.Add("hello world");
}
Run Code Online (Sandbox Code Playgroud)
为什么要有单独的对象?当然你可以这样做:
List<string> myStrs;
// ...
lock(myStrs)
{
myStrs.Add("hello world");
}
Run Code Online (Sandbox Code Playgroud) 我有一个频繁激发的System.Threading.Timer(为了简单起见,让我们说每一秒),在CallBack中我需要调用一个Action(通过构造函数传入,因此位于另一个类中)我在其中进行一些处理(假设它需要2秒以上),我如何防止多次调用处理逻辑?似乎lock()在Action调用中不起作用?我正在使用.net 3.5.
public TestOperation(Action callBackMethod)
{
this.timer = new System.Threading.Timer(timer_Elapsed, callbackMethod, timerInterval, Timeout.Infinite);
}
private void timer_Elapsed(object state)
{
Action callback = (Action) state;
if (callback != null)
{
callback();
}
}
// example of the callback, in another class.
private void callBackMethod()
{
// How can I stop this from running every 1 second? Lock() doesn't seem to work here
Thread.Sleep(2000);
}
Run Code Online (Sandbox Code Playgroud)
谢谢!
我有下面的代码(但不起作用)..我需要等到线程完成其工作然后执行然后下一个命令
private void btnPaste_Click(object sender, EventArgs e)
{
if (copiedItems != null)
{
if (copy)
{
System.Threading.Thread thPASTE = new System.Threading.Thread(PasteFromCopy);
thPASTE.Start(currAddress);
lock (this)
{
btnRefresh_Click(sender, e);
}
}
else
{
System.Threading.Thread thPASTE = new System.Threading.Thread(PasteFromMove);
thPASTE.Start(currAddress);
lock (this)
{
btnRefresh_Click(sender, e);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
粘贴应该做一些代码,然后我应该刷新列表即时显示..我需要这样做,因为它不适用于我,当我调用线程中的刷新
我怎么办?
据我从同事和网络上了解到,锁定正在同步的对象是不好的做法,但我不明白为什么?
以下类应该将设置加载到字典中,并且它还有一种方法来检索设置.
public class TingbogSettingService : ITingbogSettingService
{
private readonly ISettingRepository _settingRepository;
private readonly ICentralLog _centralLog;
private Dictionary<string, ISetting> _settingDictionary = new Dictionary<string, ISetting>();
public TingbogSettingService(ISettingRepository settingRepository, ICentralLog centralLog)
{
_settingRepository = settingRepository;
_centralLog = centralLog;
}
public ISetting GetSetting(string settingName)
{
ISetting setting;
if (!_settingDictionary.TryGetValue(settingName, out setting))
{
return null;
}
return setting;
}
public void LoadSettings()
{
var settings = _settingRepository.LoadSettings();
try
{
lock (_settingDictionary)
{
_settingDictionary = settings.ToDictionary(x => x.SettingName);
}
}
catch (Exception ex)
{
_centralLog.Log(Targets.Database, …Run Code Online (Sandbox Code Playgroud)