C # lock in common function

I have a class like this:

public static class CacheManager { static object lockObject = new object(); static MemcachedClient CacheObject { get { if (!MemcachedClient.Exists(Settings.Default .CacheInstanceName)) { MemcachedClient.Setup(Settings.Default .CacheInstanceName, new string[] {Settings.Default .CacheHostAddress}); } // // return MemcachedClient.GetInstance(Settings .Default.CacheInstanceName); } } public static List<TData> Get<TData>(string key, Func<List<int>> getListCallback, Func<int, TData> getItemCallback) where TData : class { var result = new List<TData>(); // // var list = CacheObject.Get(key); if (list == null) { lock (lockObject) { list = CacheObject.Get(key); if (list == null) { list = getListCallback(); CacheObject.Set(key, list); // // foreach (var id in (List<int>)list) { var item = getItemCallback(id); result.Add(item); CacheObject.Set(string.Concat(key, id), item); } } } } else { foreach (var id in (List<int>)list) { var itemKey = string.Concat(key, id); // // var item = CacheObject.Get(itemKey); if (item == null) { lock (lockObject) { item = CacheObject.Get(itemKey); if (item == null) { item = getItemCallback(id); CacheObject.Set(itemKey, item); } } } // // result.Add((TData)item); } } // // return (List<TData>)result; } public static void Remove(string key) { CacheObject.Delete(key); } } 

it is used in repository classes:

 public class NewsRepository : BaseRepository, IRepository { public List<News> FindAll() { return CacheManager.Get<News>(key, () => clientEntities.News.OrderByDescending(n => n.DateCreated).Select(n => n.NewsId).ToList(), (id) => clientEntities.News.Single(n => n.NewsId == id)); } } public class PagesRepository : BaseRepository { public List<Page> FindAll() { return CacheManager.Get<Page>(key, () => clientEntities.Pages.OrderBy(p => p.PageId).Select(p => p.PageId).ToList(), (id) => clientEntities.Pages.Single(p => p.PageId == id)); } } 

my question is: for example, NewsRepository did not find the news in the cache and got a lock and started loading data, but at that moment PagesRepository did not find the pages in the cache. will the PagesRepository CacheManager lock NewsRepository or (it seems to me) the NewsRepository CacheManager is another static class and its internal locks do not affect the PagesRepository CacheManager?

+4
source share
2 answers

A static field of a non-generic type (that is, not nested in a generic type, etc.) exists only once, so all locks will be conflicting.

If (comments) your goal is to make a lock for each type (from a common method), then perhaps the best way to do this is:

 public static class CacheManager { static class TypeLock<T> { public static readonly object SyncLock = new object(); } ... void SomeGenericMethod<TData>(args) { ... lock(TypeLock<TData>.SyncLock) { ... } ... } } 

Here SyncLock exists once (and only once) per T , therefore per TData . This allows you to preserve the existing API (where the CacheManager not shared).

+11
source

Both will use the same link for lockObject and therefore the same lock.

+5
source

Source: https://habr.com/ru/post/1385062/


All Articles