Я работаю над уровнем кэширования на веб-сервере на стороне сервера, используя общее кэширование Azure, чтобы уменьшить количество запросов к базе данных и, таким образом, ускорить работу (надеюсь). Я зацикливаюсь на том, как сделать весь поток endevour безопасным. Кажется, я не нашел надежного и удобного способа заблокировать ключи в 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».
Фактически, невозможно добавить что-либо новое в кеш, единственное, что можно сделать, это заменить то, что уже есть (что будет ничем).
Мне кажется, что я вынужден использовать оптимистичный «Put» в случае, когда «GetAndLock» генерирует исключение «ничего там». Однако, согласно тому, что я читал, оптимистичный «Put» разрушает любую существующую блокировку, достигнутую с помощью «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 является неполной функцией и полностью непригодна для использования. Я что-то упускаю? Есть ли способ решить эту проблему?
Все, что мне не хватает, - это способ превентивно заблокировать ключ до того, как на нем что-нибудь сохранится.
forceLock
, где msdn говорит: Если forceLock истинно, ключ блокируется независимо от наличия пары ключ-значение в кеше. Разве это не поможет вам заблокировать ключ, даже если состояние для этого ключа не существует? - person psulek   schedule 23.04.2015