Я работаю над слоем кеширования на веб-сервере на сервере, используя совместное кеширование Azure, чтобы уменьшить количество запросов к базе данных и, таким образом, сделать работу быстрее (надеюсь). То, что я застрял в том, как сделать весь endevour поток безопасным. Кажется, я не нашел надежного и удобного способа блокировки ключей в DataCache. То, что мне не хватает, - это способ предварительно заблокировать ключ, прежде чем на нем что-нибудь сохранится, чтобы я мог добавить значение без риска другого потока, пытающегося сделать то же самое в одно и то же время.Добавление элемента в Microsoft.ApplicationServer.Caching.DataCache с пессимистической блокировкой?
Я смотрю исключительно на пессимистическую блокировку до сих пор, так как это то, как безопасность потоков имеет для меня наибольший смысл, я хочу быть уверенным, что материал, над которым я работаю, заблокирован.
Я понял, что если я использую пессимистическую блокировку, я несу ответственность за использование только тех методов, которые связаны с этим. Смешивание вещей испортило бы все механизмы блокировки (источник: http://go4answers.webhost4life.com/Example/datacacheput-unlocking-key-77158.aspx).
So basicly I only have access to these methods:
value GetAndLock(key, out DataCacheLockHandle);
void PutAndUnlock(key, value, DataCacheLockHandle);
void Unlock(key, DataCacheLockHandle);
Беда в том, «GetAndLock» бросает исключение, если я пытаюсь получить то, что не в кэше. В то же время мой единственный способ добавить что-то в кеш - это «PutAndUnlock», и его нельзя использовать, если я не сделал успешный «GetAndUnlock».
Фактически, невозможно добавить что-либо новое в кэш, но только то, что можно сделать, это заменить те вещи, которые уже есть (что ничего не будет).
Так что мне кажется, что я вынужден использовать оптимистичный «Путь» в случае, когда «GetAndLock» выбрасывает исключение. В соответствии с тем, что я прочитал, оптимистичный «Путь» уничтожает любой существующий замок, достигнутый с помощью «GetAndLock», чтобы уничтожить всю попытку безопасности потока.
Example plan:
1. Try to GetAndLock
2. In case of nothing there exception:
- Put a dummy item on the key.
- GetAndLock again.
3. We have a lock, do computations, query database etc
4. PutAndUnlock the computed value
One of probably several ways it would screw up:
Thread1: Tries to GetAndLock, gets nothing there exception
Thread2: Tries to GetAndLock, gets nothing there exception
Thread1: Put a dummy item on the key
Thread1: GetAndLock again, lock achieved
Thread2: Put a dummy item on the key (destroying Thread1:s lock)
Thread2: GetAndLock again, lock achieved
Thread1: We think we have a lock, do computations, query database etc
Thread2: We have a lock, do computations, query database etc
Thread1: PutAndUnlock the computed value (will this throw an exception?)
Thread2: PutAndUnlock the computed value
В основном две нити могут писать разные вещи одному и тому же ключу в одно и то же время, игнорируя блокировки, которые оба они считают.
Мое единственное заключение заключается в том, что пессимистическая блокировка DataCache является неполной и полностью непригодной для использования. Я что-то упускаю? Есть ли способ решить это?
Все, что мне не хватает, - это способ предварительно заблокировать ключ, прежде чем что-нибудь сохранится на нем.
GetAndLock имеет параметр 'forceLock', где говорит MSDN: Если forceLock правда, ключ заблокирован независимо присутствия пары ключ-значение в кеше. Не может это помочь вам заблокировать ключ, даже если для этого ключа не существует состояния? – psulek