问题
I have got the following code:
public void Update(Foo foo)
{
lock(_locker)
{
UpdateFirstPart(foo.First);
UpdateSecondPart(foo.Second);
UpdateThirdPart(foo.Third);
}
}
public class Foo
{
public int Id;
public Some1 First;
public Some2 Second;
public Some3 Third;
}
Method Update
can be performed in two or more threads and I use lock
to prevent cuncurency problems with foo
. But I would like to lock only those Foo
that have similar Id
. For instance if one thread executes method Update
with Foo.Id = 1 and another thread executes Update
with Foo.Id = 2 then lock
is not needed and if two threads execute Update with two instances Foo
with the same Id
, lock
is needed. Is it possible to create a such lock?
回答1:
You could use ConcurrentDictionary<TKey, TValue> for storing your locks.
private static readonly ConcurrentDictionary<int, object> ThreadLockDict =
new ConcurrentDictionary<int, object>();
And use it in Update method:
public static void Update(Foo foo)
{
// add a new locker object for each foo if it's not already in dictionary
ThreadLockDict.TryAdd(foo.Id, new object());
lock (ThreadLockDict[foo.Id])
{
// some code
}
}
回答2:
You could use this class to get a lock object for every Id:
public class MultiLockObjects<TKey>
{
private readonly ConcurrentDictionary<TKey, Object> _multiLocker = new ConcurrentDictionary<TKey, Object>();
public Object this[TKey key]
{
get
{
Object lockObj = _multiLocker.GetOrAdd(key, tKey => new Object());
return lockObj;
}
}
}
Then hold an instance of it in your class:
private MultiLockObjects<int> _idLocks = new MultiLockObjects<int>();
Usage is simple:
public void Update(Foo foo)
{
Object idLockObject = _idLocks[foo.Id];
lock (idLockObject)
{
UpdateFirstPart(foo.First);
UpdateSecondPart(foo.Second);
UpdateThirdPart(foo.Third);
}
}
回答3:
You can just lock(foo)
when you're sure
- no other code is using
foo
to lock on - reference equality (identity) is acceptable/usable, this is not using
Id
You can not lock on int Id
.
Part 2,
Alas I use different instances of Foo with the same Id
Then you could try a ConcurrentDictionary<int, object>
to store a different _locker per Id. But that adds some overhead, and the problem of cleaning up that Dictionary when you run it for longer periods.
来源:https://stackoverflow.com/questions/46888590/how-to-lock-objects-withthe-same-ids