views:

252

answers:

1

sorry i have many questions about the lock/cache.=_=..

->1. about cache, i know that the cache in asp.net is threadsafe, the simple code i usually use is

    IList<User> user= HttpRuntime.Cache["myCacheItem"] as IList<User>;
    if (user == null)
    { 
       //should i have a lock here?
       //lock(some_static_var){...}
       HttpRuntime.Cache["myCacheItem"] = GetDateFromDateBase();
    }

    return user;

should use a lock in the code?

->->1.1 if i use, maybe i should declare many lockitem? i have seen some implementation in community server, it use a static dictionary to store the lockitem, is it a good idea? cause i am worried that it maybe too many lockitems in the dictionary and it maybe slow down the system.

->->1.2 if i don't use, what will happen? just maybe two or more threads access the GetDateFromDateBase()? if just this, i think maybe i can give up the lock.

->2.i have a generic dictionary stored in the cache, i have to modify(add/update/delete) it. and i just use it to get the value like dic.trygetvalue(key), don't loop it.

->->2.1 if i can guarantee that the modify is just happen in only one thread, the scene like
a.aspx -> read the dictionary from cache, and display on the page, public for user
b.ashx -> will modify the dictionary when call it.(loop in 5 minutes),private used

should i use lock in a/b? lock reader and writer?
->->->2.11 if i don't use any lock, what will happened? will it throw exception when the reader and writer access on the same time?
->->->2.12 if i just lock the writer in b.ashx, what will happen? will the reader in a.aspx blocked? and what's the best practice to deal with this situation?

->->2.2 if the reader and writer both occured in the multi threads access. they are both the in public page.
a.aspx -> just read from cache
b.aspx -> modify the dictionary

what to do? lock all?

->->2.3 if i implement a new dictionary add function:
it just copy the current dictionary to a new dictionary and then add the new item or modify and at last return the new dic,,will it solve the concurrency problem?

will the hashtable solve these problem?

how to determine a item need be locked? i think i'm wrong in these things=_=.

->3.the last question..i have two web application
a -> show the web
b -> mamage some settings
they both have own cache, what can i concurrent the two cache?
will the operation in [2.1] right or other operation?(i test memcached but it too slow than in the web application, so i just use two)

thank you for reading all-_-...
wish you can know what i say:)

Update======================================================
Thanks for Aaron's answer. after read his answer, i try to answer myself:)
1. about cache, if the data will not modify, it can read into cache first in Application_Start(global.asax).
1.1 If lock, i should add lock start when reading the data, not only writing. the lock item should static but i also feel uncerrain about 1.1.
1.2 Yes, if you can premise that the code is just read date from database and then insert into cache and will not modify(right?-_-). the result of this maybe read several times from database. i think this is not a big problem.

2. the generic dictionary write is not threadsafe, so it should be lock when modify. To solve this, i can use a immutable dictionary.
but if i use a ConcurrentDictionary(threadsafe when read/write) in .net4.0 or i implement a new dictionary(use reader-writer lock) myself, will it solve? Do i need lock it again when modify? the code is like

ConcurrentDictionary user= HttpRuntime.Cache["myCacheItem"] as ConcurrentDictionary;
if (user == null)
{ 
   //is it safe when the user is ConcurrentDictionary?
   HttpRuntime.Cache["myCacheItem"] = GetDateFromDateBase();
}
else
{
    //is it safe when the user is ConcurrentDictionary?
    user["1"] = a_new_user;
}


3.the question is that, i have a small application like a stroe, it have two web application one is the store show site(A) and the other is the management site(B), so i need to concurrnt two web cache, like that if i modify a product price in B, how can i notify site A to change/delete cache?(i know that the cache in A can set shortor, but it not quickly, so i want to know wheather there have a inner support in asp.net or just like question 2.1? have a aspx/ashx page to call?)

+1  A: 

Thread-safe means that you do not have to worry about multiple threads reading and writing the same individual cache item at the same time. You do not need any kind of lock for simple reads and writes.

However, if you are trying to perform what should be an atomic operation - for example, checking for the presence of an item and adding it if it doesn't exist - then you need to synchronize or serialize access. Because the lock needs to be global, it is usually best to declare a static readonly object in your global.asax and lock that before performing the atomic operation. Note that you should lock before the read and only release the lock after the write, so your hypothetical lock in your example above is actually happening too late.

This is why many web applications don't lazy-load the cache; instead, they perform the load in the Application_Start method. At the very least, putting an empty dictionary into the cache would save you the trouble of checking for null, and this way you wouldn't have to synchronize because you would only be accessing the cache item once (but read on).

The other aspect to the problem is, even though the cache itself is thread-safe, it does not make any items you add to it thread-safe. That means that if you store a dictionary in there, any threads that retrieve the cache item are guaranteed to get a dictionary that's fully-initialized, but you can still create race conditions and other thread-safety issues if you have multiple requests trying to access the dictionary concurrently with at least one of them modifying it.

Dictionaries in .NET can support multiple concurrent readers but not writers, so you definitely can run into issues if you have a single dictionary stored in the ASP.NET cache and have multiple threads/requests reading and writing. If you can guarantee that only one thread will ever write to the dictionary, then you can use the Dictionary as an immutable type - that is, copy the dictionary, modify the copy, and replace the original in the cache with the copy. If the dictionary is infrequently-modified, then this would indeed save you the trouble of synchronizing access, because no request will ever be trying to read from the same dictionary that is being modified. On the other hand, if the dictionary is very large and/or frequently modified, then you could run into performance issues making all those copies - the only way to be sure is profile, profile, profile!

If you find that performance constraints don't allow to use that approach, then the only other option is to synchronize access. If you know that only one thread will ever modify the dictionary at a time, then a reader-writer lock (i.e. ReaderWriterLockSlim) should work well for you. If you can't guarantee this, then you need a Monitor (or just a simple lock(...) clause around each sequence of operations).

That should answer questions 1-2; I'm sorry but I don't quite understand what you're asking in #3. ASP.NET applications are all instantiated in their own AppDomains, so there aren't really any concurrency issues to speak of because nothing is shared (unless you are actually using some method of IPC, in which case everything is fair game).

Have I understood your questions correctly? Does this help?

Aaronaught
thanks for your help:)
wingoo