মেমোরিচেড থ্রেড সুরক্ষা, লক করা কি প্রয়োজনীয়?


91

আরম্ভকারীদের জন্য আমাকে এটি কেবল এখানে ফেলে দিন যে আমি জানি যে নীচের কোডটি থ্রেড নিরাপদ নয় (সংশোধন: হতে পারে)। আমি যেটির সাথে লড়াই করছি তা হ'ল এমন একটি বাস্তবায়ন খুঁজে পাওয়া যা আমি আসলে পরীক্ষার অধীনে ব্যর্থ হতে পারি। আমি এখনই একটি বড় ডাব্লুসিএফ প্রকল্পটি রিফ্যাক্টর করছি যার জন্য কিছু (বেশিরভাগ) স্থিতিশীল ডেটা থাকা দরকার এবং এটি একটি এসকিউএল ডাটাবেস থেকে পপুলেটেড। দিনে অন্তত একবার এটির মেয়াদ শেষ হয়ে যাওয়া এবং "রিফ্রেশ" করা দরকার যার কারণে আমি মেমোরিচ্যাচ ব্যবহার করছি।

আমি জানি যে নীচের কোডটি থ্রেড নিরাপদ হওয়া উচিত নয় তবে ভারী বোঝার নিচে ব্যর্থ হওয়া এবং বিষয়গুলিকে জটিল করতে গুগল অনুসন্ধান কার্যকরভাবে উভয় উপায়ে (প্রয়োজনীয় তালিকাগুলির সাথে এবং লকগুলি ছাড়াও প্রয়োজনীয় প্রয়োজন কিনা তা দেখায়) get

একাধিক থ্রেড পরিবেশে মেমোরি ক্যাশের জ্ঞানযুক্ত কেউ কি আমাকে যথাযথভাবে লক করতে হবে কিনা তা আমাকে নিশ্চিতভাবে জানাতে পারে যাতে রিমুভাল / রিপোপুলেশন চলাকালীন একটি কল (যা খুব কমই বলা হবে তবে এটি প্রয়োজনীয়তা হবে) সরাতে পারে না।

public class MemoryCacheService : IMemoryCacheService
{
    private const string PunctuationMapCacheKey = "punctuationMaps";
    private static readonly ObjectCache Cache;
    private readonly IAdoNet _adoNet;

    static MemoryCacheService()
    {
        Cache = MemoryCache.Default;
    }

    public MemoryCacheService(IAdoNet adoNet)
    {
        _adoNet = adoNet;
    }

    public void ClearPunctuationMaps()
    {
        Cache.Remove(PunctuationMapCacheKey);
    }

    public IEnumerable GetPunctuationMaps()
    {
        if (Cache.Contains(PunctuationMapCacheKey))
        {
            return (IEnumerable) Cache.Get(PunctuationMapCacheKey);
        }

        var punctuationMaps = GetPunctuationMappings();

        if (punctuationMaps == null)
        {
            throw new ApplicationException("Unable to retrieve punctuation mappings from the database.");
        }

        if (punctuationMaps.Cast<IPunctuationMapDto>().Any(p => p.UntaggedValue == null || p.TaggedValue == null))
        {
            throw new ApplicationException("Null values detected in Untagged or Tagged punctuation mappings.");
        }

        // Store data in the cache
        var cacheItemPolicy = new CacheItemPolicy
        {
            AbsoluteExpiration = DateTime.Now.AddDays(1.0)
        };

        Cache.AddOrGetExisting(PunctuationMapCacheKey, punctuationMaps, cacheItemPolicy);

        return punctuationMaps;
    }

    //Go oldschool ADO.NET to break the dependency on the entity framework and need to inject the database handler to populate cache
    private IEnumerable GetPunctuationMappings()
    {
        var table = _adoNet.ExecuteSelectCommand("SELECT [id], [TaggedValue],[UntaggedValue] FROM [dbo].[PunctuationMapper]", CommandType.Text);
        if (table != null && table.Rows.Count != 0)
        {
            return AutoMapper.Mapper.DynamicMap<IDataReader, IEnumerable<PunctuationMapDto>>(table.CreateDataReader());
        }

        return null;
    }
}

অবজেক্ট ক্যাশে থ্রেড নিরাপদ, আমি মনে করি না যে আপনার ক্লাস ব্যর্থ হতে পারে। msdn.microsoft.com/en-us/library/… আপনি একই সাথে ডাটাবেসে যাচ্ছেন তবে এটি কেবল প্রয়োজনের চেয়ে বেশি সিপিইউ ব্যবহার করবে।
the_lotus

4
যখন অবজেক্ট ক্যাশে থ্রেড নিরাপদ, এটির বাস্তবায়ন নাও হতে পারে। এইভাবে মেমোরি ক্যাশে প্রশ্ন।
হ্যানি

উত্তর:


78

ডিফল্ট এমএস-সরবরাহ MemoryCacheসম্পূর্ণ থ্রেড নিরাপদ। যে কোনও কাস্টম বাস্তবায়ন যা থেকে প্রাপ্ত MemoryCacheথ্রেড নিরাপদ নাও হতে পারে। আপনি যদি MemoryCacheবাক্সের বাইরে প্লেইন ব্যবহার করেন তবে এটি থ্রেড নিরাপদ। আমি কীভাবে এটি ব্যবহার করি তা দেখতে আমার ওপেন সোর্স বিতরণ করা ক্যাচিং সমাধানের উত্স কোডটি ব্রাউজ করুন:

https://github.com/haneytron/dache/blob/master/Dache.CacheHost/Storage/MemCache.cs


4
ডেভিড, কেবলমাত্র নিশ্চিত করার জন্য, আমার উপরে যে খুব সাধারণ উদাহরণ শ্রেণিতে রয়েছে, কল করুন .আর সরান () আসলে কী থ্রেডটি নিরাপদ যদি গেট () কল করার প্রক্রিয়ায় থাকে? আমি মনে করি আমার কেবল প্রতিফলক ব্যবহার করা উচিত এবং আরও গভীর খনন করা উচিত তবে সেখানে প্রচুর বিরোধী তথ্য রয়েছে।
জেমস লেগান

12
এটি থ্রেড নিরাপদ, তবে রেসের শর্তগুলির কাছে ঝুঁকিপূর্ণ ... আপনার সরানোর আগে যদি আপনার গেট হয়ে যায় তবে গেটে ডেটা ফেরত দেওয়া হবে। সরানটি যদি প্রথমে ঘটে তবে তা হবে না। এটি অনেকটা ডাটাবেজে নোংরা পাঠের মতো।
হ্যানি

10
উল্লেখ মূল্য (যেমন আমি নীচে অন্য উত্তর মন্তব্য), dotnet কোর বাস্তবায়ন বর্তমানে নয় সম্পূর্ণরূপে নিরাপদ থ্রেড। বিশেষত GetOrCreateপদ্ধতি।
গিথুব-

কনসোল ব্যবহার করে থ্রেড চালানোর সময় কি মেমোরি ক্যাশে একটি ব্যতিক্রম "মেমরির বাইরে" ফেলে দেয়?
ফাসেহ হারিস

50

অন্য উত্তরগুলি যেমন উল্লেখ করেছে মেমোরিসিচে প্রকৃতপক্ষে থ্রেড নিরাপদ, এতে একটি সাধারণ মাল্টি থ্রেডিং সমস্যা রয়েছে - যদি 2 থ্রেড একই সাথে ক্যাশে Getথেকে (বা পরীক্ষা করে Contains) দেখার চেষ্টা করে তবে উভয়ই ক্যাশে মিস করবে এবং উভয়ই উত্পাদন শেষ করবে ফলাফল এবং উভয়ই এরপরে ক্যাশে ফলাফল যুক্ত করবে।

প্রায়শই এটি অনাকাঙ্ক্ষিত - দ্বিতীয় থ্রেডটি প্রথমে সম্পূর্ণ হওয়ার জন্য অপেক্ষা করা উচিত এবং দুবার ফলাফল উত্পন্ন করার পরিবর্তে এর ফলাফলটি ব্যবহার করা উচিত।

আমি LazyCache লেখার একটি কারণ ছিল - মেমোরিচেচে একটি বন্ধুত্বপূর্ণ মোড়ক যা এই ধরণের সমস্যার সমাধান করে। এটি নুগেটেও উপলব্ধ ।


"এটিতে একটি সাধারণ বহু থ্রেডিং সমস্যা রয়েছে" এজন্য আপনার AddOrGetExistingচারপাশে কাস্টম যুক্তি প্রয়োগের পরিবর্তে আপনার যেমন পারমাণবিক পদ্ধতি ব্যবহার করা উচিত ContainsAddOrGetExistingMemoryCache পদ্ধতি পারমাণবিক এবং threadsafe referencesource.microsoft.com/System.Runtime.Caching/R/...
অ্যালেক্স

4
হ্যাঁ AddOrGetExisting থ্রেড নিরাপদ। তবে এটি ধরে নিয়েছে আপনার কাছে ইতিমধ্যে সেই সামগ্রীর একটি রেফারেন্স রয়েছে যা ক্যাশে যুক্ত হবে। সাধারণত আপনি অ্যাডওরগেটএক্সেস্টিং চান না যা আপনি "গেটএক্সিস্টিংঅর জেনারেটটিসএন্ডক্যাচিআইটি" চান যা লাজিচি আপনাকে দেয়।
অ্যালিস্টের্ট্রি

হ্যাঁ, "যদি আপনার কাছে ইতিমধ্যে বাধ্যবাধকতা না থাকে" পয়েন্টে একমত হয়েছেন
অ্যালেক্স

17

অন্যরা যেমন বলেছে, মেমোরিচেস সত্যই থ্রেড নিরাপদ। এটির মধ্যে সঞ্চিত ডেটার থ্রেড সুরক্ষাটি সম্পূর্ণরূপে আপনার এটির ব্যবহারের উপর নির্ভর করে।

সম্মতি এবং প্রকার সম্পর্কিত রিড কোপসিকে তার দুর্দান্ত পোস্ট থেকে উদ্ধৃত করা ConcurrentDictionary<TKey, TValue>। যা অবশ্যই এখানে প্রযোজ্য।

যদি দুটি থ্রেড একই সাথে [getOrAdd] কল করে তবে টিভিালুর দুটি উদাহরণ সহজেই নির্মিত যেতে পারে।

আপনি কল্পনা করতে পারেন যে এটি TValueনির্মাণে ব্যয়বহুল হলে এটি বিশেষত খারাপ ।

আপনার চারপাশে কাজ করার জন্য, আপনি Lazy<T>খুব সহজেই লাভ করতে পারেন, যা কাকতালীয়ভাবে নির্মাণ করা খুব সস্তা cheap এটি করা নিশ্চিত করে যদি আমরা বহুবিবাহিত পরিস্থিতিতে পড়ে যাই, তবে আমরা কেবল একাধিক উদাহরণ তৈরি করছি Lazy<T>(যা সস্তা)।

GetOrAdd()( GetOrCreate()এর ক্ষেত্রে MemoryCache) একই, Lazy<T>সমস্ত থ্রেডে একক হবে, "অতিরিক্ত" উদাহরণগুলি Lazy<T>কেবল ফেলে দেওয়া হবে।

যেহেতু ডাকা Lazy<T>না হওয়া পর্যন্ত কিছুই করে না .Value, কেবলমাত্র বস্তুর কেবলমাত্র একটি উদাহরণ নির্মিত হয়।

এখন কিছু কোডের জন্য! নীচে একটি এক্সটেনশন পদ্ধতি রয়েছে IMemoryCacheযার জন্য উপরেরগুলি প্রয়োগ করে। এটি নির্বিচারে SlidingExpirationএকটি int secondsপদ্ধতি প্যারামের উপর ভিত্তি করে সেট করা হচ্ছে । তবে এটি আপনার প্রয়োজনের ভিত্তিতে সম্পূর্ণ কাস্টমাইজযোগ্য।

নোট করুন এটি .netcore2.0 অ্যাপ্লিকেশানের সাথে নির্দিষ্ট

public static T GetOrAdd<T>(this IMemoryCache cache, string key, int seconds, Func<T> factory)
{
    return cache.GetOrCreate<T>(key, entry => new Lazy<T>(() =>
    {
        entry.SlidingExpiration = TimeSpan.FromSeconds(seconds);

        return factory.Invoke();
    }).Value);
}

কল করতে:

IMemoryCache cache;
var result = cache.GetOrAdd("someKey", 60, () => new object());

এই সমস্ত অ্যাসক্রোনাকলভাবে সম্পাদন করার জন্য, আমি স্টিফেন টুবের এমএসডিএন সম্পর্কিত AsyncLazy<T>তার নিবন্ধে পাওয়া দুর্দান্ত বাস্তবায়নটি ব্যবহার করার পরামর্শ দিচ্ছি । যা বিল্টিন অলস ইনিশিয়ালাইজারকে Lazy<T>প্রতিশ্রুতির সাথে সংযুক্ত করে Task<T>:

public class AsyncLazy<T> : Lazy<Task<T>>
{
    public AsyncLazy(Func<T> valueFactory) :
        base(() => Task.Factory.StartNew(valueFactory))
    { }
    public AsyncLazy(Func<Task<T>> taskFactory) :
        base(() => Task.Factory.StartNew(() => taskFactory()).Unwrap())
    { }
}   

এখন এর async সংস্করণ GetOrAdd():

public static Task<T> GetOrAddAsync<T>(this IMemoryCache cache, string key, int seconds, Func<Task<T>> taskFactory)
{
    return cache.GetOrCreateAsync<T>(key, async entry => await new AsyncLazy<T>(async () =>
    { 
        entry.SlidingExpiration = TimeSpan.FromSeconds(seconds);

        return await taskFactory.Invoke();
    }).Value);
}

এবং অবশেষে, কল করতে:

IMemoryCache cache;
var result = await cache.GetOrAddAsync("someKey", 60, async () => new object());

4
আমি এটি চেষ্টা করেছিলাম, এবং এটি কাজ করে না বলে মনে হয় (ডট নেট কোর 2.0)। প্রতিটি GetOrCreate একটি নতুন অলস দৃষ্টান্ত তৈরি করবে এবং নতুন আলস্যের সাথে ক্যাশে আপডেট হবে এবং তাই মানটি মূল্যায়িত multiple একাধিকবার তৈরি হয়েছে (একাধিক থ্রেড এনভির মধ্যে)।
অমিতি

4
এটি সৌন্দর্য থেকে .netcore 2.0 MemoryCache.GetOrCreateএকই ভাবে নিরাপদ থ্রেড নয় ConcurrentDictionaryহয়
Amite

সম্ভবত একটি নির্বোধ প্রশ্ন, তবে আপনি কি নিশ্চিত যে এটি এমন মান যা একাধিকবার তৈরি হয়েছিল এবং না Lazy? যদি তা হয় তবে আপনি এটি কীভাবে বৈধ করলেন?
পিএম

4
আমি একটি ফ্যাক্টরি ফাংশন ব্যবহার করেছি যা যখন এটি ব্যবহৃত হয় তখন স্ক্রিনে মুদ্রণ করে + একটি এলোমেলো সংখ্যা উত্পন্ন করে, এবং GetOrCreateএকই কী এবং সেই কারখানাটি ব্যবহার করার চেষ্টা করে 10 টি থ্রেড শুরু করি। ফলস্বরূপ, ফ্যাক্টরিটি 10 ​​বার ব্যবহৃত হয়েছিল যখন মেমরি ক্যাশে (প্রিন্টগুলি দেখেছিল) ব্যবহার করার সময় + প্রতিবার যখন GetOrCreateভিন্ন মূল্য ফেরত দেয়! আমি একই পরীক্ষার ব্যবহার করে চালাচ্ছি ConcurrentDicionaryএবং ফ্যাক্টরিটি একবারে ব্যবহৃত হচ্ছে দেখেছি এবং সর্বদা একই মান পেয়েছি। আমি এটিতে গিথুবে একটি বদ্ধ ইস্যু পেয়েছি , আমি কেবল সেখানে একটি মন্তব্য লিখেছিলাম যে এটি আবার খোলা উচিত
AmitE

সতর্কতা: এই উত্তরটি কাজ করছে না: অলস <T> ক্যাশেড ফাংশনটির একাধিক মৃত্যুদন্ড কার্যকর করছে না। @ স্নিকারের উত্তর দেখুন। [নেট কোর 2.0]
ফার্নান্দো সিলভা

11

এই লিঙ্কটি দেখুন: http://msdn.microsoft.com/en-us/library/system.runtime.caching.memorycache(v=vs.110).aspx

পৃষ্ঠার একেবারে নীচে যান (বা "থ্রেড সুরক্ষা" পাঠ্যের জন্য অনুসন্ধান করুন)।

তুমি দেখবে:

Read থ্রেড সুরক্ষা

এই ধরণের থ্রেড নিরাপদ।


7
আমি ব্যক্তিগত অভিজ্ঞতার উপর ভিত্তি করে এমএসডিএন এর "থ্রেড সেফ" এর সংজ্ঞা নিজের উপর বিশ্বাস করা থামিয়ে দিয়েছি। এখানে একটি ভাল পঠন: লিঙ্ক
জেমস লেগান

4
আমি উপরে প্রদত্ত লিঙ্কটির চেয়ে এই পোস্টটি কিছুটা আলাদা। পার্থক্যটি অত্যন্ত গুরুত্বপূর্ণ যে আমি যে লিঙ্কটি সরবরাহ করেছি তাতে থ্রেড সুরক্ষার ঘোষণায় কোনও সতর্কতা দেওয়া হয়নি। আমার MemoryCache.Defaultকোনও উচ্চতর ভলিউম ব্যবহার করে ব্যক্তিগত অভিজ্ঞতা রয়েছে (প্রতি মিনিটে কয়েক মিলিয়ন ক্যাশে হিট) কোনও থ্রেডিং সমস্যা নেই।
একুস্তিকমার্টিন

আমি মনে করি তাদের অর্থ হ'ল পড়ুন এবং লেখার ক্রিয়াকলাপগুলি পরমাণুর সাথে সংঘটিত হয়। সংক্ষেপে, থ্রেড এ যখন বর্তমান মানটি পড়ার চেষ্টা করে, এটি সর্বদা সম্পূর্ণ লেখার কাজগুলি পড়ে, কোনও থ্রেড দ্বারা স্মৃতিতে ডেটা লেখার মাঝখানে নয় hen যখন থ্রেড চেষ্টা করে স্মৃতিতে লেখার জন্য কোনও থ্রেড দ্বারা কোনও হস্তক্ষেপ করা সম্ভব হয়নি hatএটি আমার বোঝার তবে এটি সম্পর্কে অনেকগুলি প্রশ্ন / নিবন্ধ রয়েছে যা নীচের মতো সম্পূর্ণ সিদ্ধান্তে পৌঁছায় না। stackoverflow.com/questions/3137931/msdn-what-is-thread-safety
erhan355

3

নেট নেট ২.০ এর জন্য ইস্যুটি সমাধান করার জন্য স্যাম্পল লাইব্রেরি সদ্য আপলোড করা হয়েছে।

এই রেপো একবার দেখুন:

RedisLazyCache

আমি রেডিস ক্যাশে ব্যবহার করছি তবে কানেকশনস্ট্রিং অনুপস্থিত থাকলে এটি ফেইলওভার বা কেবল মেমোরিচিচি ব্যবহার করে।

এটি LazyCache লাইব্রেরি ভিত্তিক যা কলব্যাক কার্যকর করার জন্য খুব ব্যয়বহুল হলে বিশেষভাবে ডেটা লোড করার এবং সংরক্ষণ করার চেষ্টা করার ক্ষেত্রে মাল্টি থ্রেডিংয়ের ইভেন্টে লেখার জন্য কলব্যাকের একক প্রয়োগের গ্যারান্টি দেয়।


দয়া করে কেবল উত্তর ভাগ করুন, অন্যান্য তথ্য মন্তব্য হিসাবে ভাগ করা যায়
ইলাস্টিক কোড

4
@ ওয়েলআবাস আমি চেষ্টা করেছি তবে মনে হয় আমার প্রথমে 50 টি নামকরা দরকার। : ডি। যদিও এটি ওপি প্রশ্নের সরাসরি উত্তর নয় (কেন হ্যাঁ / না দিয়ে কিছু উত্তর দেওয়া যেতে পারে কেন তার কিছু কারণের সাথে), আমার উত্তরটি উত্তর নয় এর সম্ভাব্য সমাধানের জন্য।
ফ্রান্সিস মারাসিগান

1

@ অ্যামিটি @ জিম্বাবুয়েদের উত্তরগুলিতে যেমন উল্লেখ করেছেন, তার উদাহরণ এখানে প্রদর্শিত হিসাবে কাজ করছে না:

class Program
{
    static async Task Main(string[] args)
    {
        var cache = new MemoryCache(new MemoryCacheOptions());

        var tasks = new List<Task>();
        var counter = 0;

        for (int i = 0; i < 10; i++)
        {
            var loc = i;
            tasks.Add(Task.Run(() =>
            {
                var x = GetOrAdd(cache, "test", TimeSpan.FromMinutes(1), () => Interlocked.Increment(ref counter));
                Console.WriteLine($"Interation {loc} got {x}");
            }));
        }

        await Task.WhenAll(tasks);
        Console.WriteLine("Total value creations: " + counter);
        Console.ReadKey();
    }

    public static T GetOrAdd<T>(IMemoryCache cache, string key, TimeSpan expiration, Func<T> valueFactory)
    {
        return cache.GetOrCreate(key, entry =>
        {
            entry.SetSlidingExpiration(expiration);
            return new Lazy<T>(valueFactory, LazyThreadSafetyMode.ExecutionAndPublication);
        }).Value;
    }
}

আউটপুট:

Interation 6 got 8
Interation 7 got 6
Interation 2 got 3
Interation 3 got 2
Interation 4 got 10
Interation 8 got 9
Interation 5 got 4
Interation 9 got 1
Interation 1 got 5
Interation 0 got 7
Total value creations: 10

দেখে মনে হচ্ছে GetOrCreateসর্বদা তৈরি করা এন্ট্রি রিটার্ন। ভাগ্যক্রমে, এটি ঠিক করা খুব সহজ:

public static T GetOrSetValueSafe<T>(IMemoryCache cache, string key, TimeSpan expiration,
    Func<T> valueFactory)
{
    if (cache.TryGetValue(key, out Lazy<T> cachedValue))
        return cachedValue.Value;

    cache.GetOrCreate(key, entry =>
    {
        entry.SetSlidingExpiration(expiration);
        return new Lazy<T>(valueFactory, LazyThreadSafetyMode.ExecutionAndPublication);
    });

    return cache.Get<Lazy<T>>(key).Value;
}

এটি প্রত্যাশার মতো কাজ করে:

Interation 4 got 1
Interation 9 got 1
Interation 1 got 1
Interation 8 got 1
Interation 0 got 1
Interation 6 got 1
Interation 7 got 1
Interation 2 got 1
Interation 5 got 1
Interation 3 got 1
Total value creations: 1

4
এটিও কাজ করে না। এটি বেশ কয়েকবার চেষ্টা করে দেখুন এবং আপনি দেখতে পাবেন যে কখনও কখনও মানটি সর্বদা 1 হয় না
বিরামহীন

1

ক্যাশে থ্রেডসেফ, তবে অন্যদের মতোই এটিও সম্ভব হয়েছে যে একাধিক প্রকারের কল পেলে getOrAdd ফানকে একাধিক ধরণের কল করবে।

এটি আমার ন্যূনতম স্থির

private readonly SemaphoreSlim _cacheLock = new SemaphoreSlim(1);

এবং

await _cacheLock.WaitAsync();
var data = await _cache.GetOrCreateAsync(key, entry => ...);
_cacheLock.Release();

আমি এটি একটি ভাল সমাধান মনে করি, তবে আমার যদি একাধিক পদ্ধতিতে বিভিন্ন ক্যাশে পরিবর্তন হয় তবে আমি লকটি ব্যবহার করলে তারা প্রয়োজন ছাড়াই লক হয়ে যায়! এক্ষেত্রে আমাদের একাধিক _ ক্যাচলক থাকা উচিত, আমি মনে করি ক্যাচলকের কাছে কী কী থাকলে আরও ভাল হত!
ড্যানিয়েল

এটি সমাধানের অনেকগুলি উপায় রয়েছে, একটি জেনেরিকস হ'ল মাইকেচে <টি> এর উদাহরণ অনুসারে সেমফোরটি অনন্য হবে। তারপরে আপনি এটিকে অ্যাডসিংলেটন (typof (IMyCache <>), টাইপফ (MyCache <>)) নিবন্ধভুক্ত করতে পারেন;
অ্যান্ডারস

আপনার সম্ভবত অন্যান্য ক্ষণস্থায়ী প্রকারের প্রয়োজন হলে আমি পুরো ক্যাশেটিকে একটি সিঙ্গলটন তৈরি করতে পারি যা সমস্যার কারণ হতে পারে। সুতরাং সম্ভবত একটি সেমফোর স্টোর আইসিচেলক <T> যা সিঙ্গলটন
অ্যান্ডারস

এই সংস্করণটির সমস্যাটি হ'ল যদি আপনার একই সাথে ক্যাশে 2 টি আলাদা জিনিস থাকে তবে দ্বিতীয়টির জন্য ক্যাশে চেক করার আগে আপনাকে প্রথমটি উত্পাদন শেষ করতে অপেক্ষা করতে হবে। কীগুলি আলাদা থাকলে একই সাথে ক্যাশে (এবং উত্পন্ন করা) পরীক্ষা করতে সক্ষম হওয়া তাদের উভয়ের পক্ষে আরও দক্ষ। আপনার আইটেমগুলি যত তাড়াতাড়ি সম্ভব ক্যাশে তা নিশ্চিত করতে LazyCache অলস <T> এবং স্ট্রিপড লকিংয়ের সংমিশ্রণ ব্যবহার করে এবং কেবল প্রতি একবার কী তৈরি করে। দেখাGithub.com/alastairtree/lazycache
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.