Замена значения, связанного с ключом ConcurrentDictionary, блокирует любые операции словаря за пределами этого ключа?Замена операций с разными ключами ConcurrentDictionary на один замок?
EDIT: Например, я хотел бы знать, если один поток будет когда-либо блокировать другой, к тому же, когда ключи сначала добавляются в следующем:
public static class Test {
private static ConcurrentDictionary<int, int> cd = new ConcurrentDictionary<int, int>();
public static Test() {
new Thread(UpdateItem1).Start();
new Thread(UpdateItem2).Start();
}
private static void UpdateItem1() {
while (true) cd[1] = 0;
}
private static void UpdateItem2() {
while (true) cd[2] = 0;
}
}
Первоначально я предполагал его делает, потому что, например, dictionary[key] = value;
может ссылаться на ключ, которого пока нет. Однако, работая, я понял, что если добавление необходимо, это может произойти после отдельной эскалации блокировки.
Я разрабатывал следующий класс, но косвенность, предоставляемая классом AccountCacheLock
, не нужна, если ответ на этот вопрос (см. Выше) - «нет». На самом деле, все мои собственные блокировки практически не нужны.
// A flattened subset of repository user values that are referenced for every member page access
public class AccountCache {
// The AccountCacheLock wrapper allows the AccountCache item to be updated in a locally-confined account-specific lock.
// Otherwise, one of the following would be necessary:
// Replace a ConcurrentDictionary item, requiring a lock on the ConcurrentDictionary object (unless the ConcurrentDictionary internally implements similar indirection)
// Update the contents of the AccountCache item, requiring either a copy to be returned or the lock to wrap the caller's use of it.
private static readonly ConcurrentDictionary<int, AccountCacheLock> dictionary = new ConcurrentDictionary<int, AccountCacheLock>();
public static AccountCache Get(int accountId, SiteEntities refreshSource) {
AccountCacheLock accountCacheLock = dictionary.GetOrAdd(accountId, k => new AccountCacheLock());
AccountCache accountCache;
lock (accountCacheLock) {
accountCache = accountCacheLock.AccountCache;
}
if (accountCache == null || accountCache.ExpiresOn < DateTime.UtcNow) {
accountCache = new AccountCache(refreshSource.Accounts.Single(a => a.Id == accountId));
lock (accountCacheLock) {
accountCacheLock.AccountCache = accountCache;
}
}
return accountCache;
}
public static void Invalidate(int accountId) {
// TODO
}
private AccountCache(Account account) {
ExpiresOn = DateTime.UtcNow.AddHours(1);
Status = account.Status;
CommunityRole = account.CommunityRole;
Email = account.Email;
}
public readonly DateTime ExpiresOn;
public readonly AccountStates Status;
public readonly CommunityRoles CommunityRole;
public readonly string Email;
private class AccountCacheLock {
public AccountCache AccountCache;
}
}
Боковой вопрос: есть ли что-то в структуре ASP.NET, которая уже делает это?
На какой точный замок следует полагаться? Я еще не совсем понял, чего вы пытаетесь достичь ... –
Эй, Джон. Я не уверен, что понимаю ваш запрос на разъяснение; Я почти уверен, что этого не хватает, но я не могу понять, что это такое. Я попытаюсь повторить: я хочу заменить элемент в словаре, не блокируя добавление других элементов или блокируя чтение или замену других значений ключа. Нужен ли мне дополнительный блокирующий слой, который я добавил с помощью AccountCacheLock в моем собственном коде выше, или я могу просто вызвать 'ConcurrentDictionary [key] ='? – shannon
В конечном счете, я просто пытаюсь создать кэш для часто используемой учетной записи (и дочерней) информации, указанной в идентификаторе учетной записи.Я был обеспокоен тем, что если я просто попрошу совпадающий словарь заменить элемент, я заблокирую все потоки от использования кеша на время замены. – shannon