একটি হ্যাশম্যাপ থ্রেড-কি বিভিন্ন কীগুলির জন্য নিরাপদ?


87

যদি আমার কাছে দুটি হ্যাশম্যাপ অ্যাক্সেস করার জন্য একাধিক থ্রেড থাকে, তবে গ্যারান্টি দেয় যে তারা একই সময়ে একই কীটি অ্যাক্সেস করবে না, তা কি এখনও রেসের অবস্থার দিকে নিয়ে যেতে পারে?

উত্তর:


100

@ ডটসিডের উত্তরে তিনি বলেছেন:

আপনি যদি কোনওভাবেই হ্যাশম্যাপ পরিবর্তন করেন তবে আপনার কোডটি কেবল ভেঙে গেছে।

সে ঠিক আছে। সিঙ্ক্রোনাইজেশন ব্যতীত আপডেট হওয়া একটি হ্যাশম্যাপটি ভেঙে যাবে এমনকি থ্রেডগুলি কীগুলির বিচ্ছিন্ন সেট ব্যবহার করছে। এখানে কিছু জিনিস ভুল হতে পারে।

  • যদি একটি থ্রেড একটি করে put, তবে অন্য থ্রেড হ্যাশম্যাপের আকারের জন্য একটি বাসি মান দেখতে পারে।

  • যখন কোনও থ্রেডটি putটেবিলটির পুনর্নির্মাণকে ট্রিগার করে তখন অন্য থ্রেডটি হ্যাশটেবল অ্যারে রেফারেন্সের আকার, এর বিষয়বস্তু বা হ্যাশ চেইনের ক্ষণস্থায়ী বা বাসি সংস্করণগুলি দেখতে পারে। বিশৃঙ্খলা পরিণতি হতে পারে।

  • যখন কোনও থ্রেড putএকটি কীটির জন্য কাজ করে যা অন্য কোনও থ্রেড দ্বারা ব্যবহৃত কিছু কীটির সাথে সংঘর্ষে আসে এবং পরবর্তী থ্রেডটি putতার কীটির জন্য একটি করে , তখন পরবর্তীটি হ্যাশ চেইন রেফারেন্সের একটি বাসি অনুলিপি দেখতে পারে। বিশৃঙ্খলা পরিণতি হতে পারে।

  • যখন কোনও থ্রেডটি এমন চাবি দিয়ে টেবিলে অনুসন্ধান করে যা অন্য কোনও থ্রেডের কীগুলির সাথে সংঘর্ষিত হয়, তখন এটি চেইনে সেই কীটির মুখোমুখি হতে পারে। এটি সেই কীতে সমান কল করবে এবং থ্রেডগুলি সিঙ্ক্রোনাইজ করা না থাকলে সমান পদ্ধতিতে কীটিতে বাসি অবস্থায় আসতে পারে।

এবং যদি আপনার একসাথে দুটি থ্রেড থাকে putবা removeঅনুরোধ থাকে তবে জাতি শর্তের জন্য অসংখ্য সুযোগ রয়েছে।

আমি তিনটি সমাধান সম্পর্কে চিন্তা করতে পারি:

  1. ব্যবহার ক ConcurrentHashMap
  2. একটি নিয়মিত ব্যবহার HashMapকরুন তবে বাইরে সিঙ্ক্রোনাইজ করুন; যেমন আদিম মিটেক্সেস, Lockঅবজেক্টস, ইত্যাদি ব্যবহার করে ।
  3. HashMapপ্রতিটি থ্রেডের জন্য আলাদা ব্যবহার করুন । যদি থ্রেডগুলিতে কীগুলির একটি বিচ্ছিন্ন সেট থাকে তবে তাদের একটি একক মানচিত্র ভাগ করে নেওয়ার দরকার নেই (অ্যালগোরিদমিক দৃষ্টিকোণ থেকে)। প্রকৃতপক্ষে, যদি আপনার অ্যালগরিদমগুলি কোনও পর্যায়ে মানচিত্রের কী, মান বা এন্ট্রিগুলিকে পুনরাবৃত্তি করে থ্রেডগুলিতে জড়িত থাকে তবে একক মানচিত্রকে একাধিক মানচিত্রে বিভক্তকরণ প্রক্রিয়াজাতকরণের সেই অংশটির জন্য গুরুত্বপূর্ণ গতিবেগ দিতে পারে।

30

কেবলমাত্র একটি কনক্র্যান্টহ্যাশম্যাপ ব্যবহার করুন। কনক্র্যান্টহ্যাশম্যাপে একাধিক লক ব্যবহার করা হয় যা একটি লকের প্রতিযোগিতা হওয়ার সম্ভাবনা হ্রাস করতে হ্যাশ বালতিগুলির একটি পরিসীমা জুড়ে। অবিযুক্ত লকটি অর্জন করার জন্য একটি প্রান্তিক কর্মক্ষমতা প্রভাব রয়েছে is

আপনার মূল প্রশ্নের উত্তর দিতে: জাভাডোকের মতে, যতক্ষণ মানচিত্রের কাঠামো পরিবর্তন হয় না ততক্ষণ আপনার ঠিক আছে। এর অর্থ হ'ল উপাদানগুলি সরানো নয় এবং মানচিত্রে ইতিমধ্যে নেই এমন নতুন কী যুক্ত করা হবে না no বিদ্যমান কীগুলির সাথে যুক্ত মানটি প্রতিস্থাপন করা ঠিক আছে।

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

যদিও এটি দৃশ্যমানতা সম্পর্কে কোনও গ্যারান্টি দেয় না। সুতরাং আপনাকে মাঝে মাঝে বাসী সমিতি পুনরুদ্ধার করতে স্বীকার করতে হবে।


6

এটি "অ্যাক্সেস" এর নীচে আপনি কী বোঝাতে চান তার উপর নির্ভর করে। আপনি যদি কেবলমাত্র পড়েন তবে আপনি একই কীগুলি ততক্ষণ পড়তে পারবেন যতক্ষণ না " ঘটনার আগে " নিয়মের আওতায় গ্যারান্টিযুক্ত ডেটা দৃশ্যমান হয় । এর অর্থ HashMapকোনও পাঠক অ্যাক্সেস করা শুরু করার আগে পরিবর্তন করা উচিত নয় এবং সমস্ত পরিবর্তন (প্রাথমিক নির্মাণ) সম্পূর্ণ করা উচিত HashMap

আপনি যদি কোনওভাবে পরিবর্তন করেন HashMapতবে আপনার কোডটি কেবল ভেঙে গেছে। @ স্টেফেন সি খুব ভাল ব্যাখ্যা সরবরাহ করেছে কেন।

সম্পাদনা: প্রথম ক্ষেত্রেটি যদি আপনার আসল পরিস্থিতি হয় তবে আমি আপনাকে পরামর্শ দিচ্ছি Collections.unmodifiableMap()যে আপনার হ্যাশম্যাপটি কখনই পরিবর্তিত হবে না ure যে বিষয়গুলি দ্বারা চিহ্নিত করা হয়েছে HashMapসেগুলিও পরিবর্তন করা উচিত নয়, তাই finalকীওয়ার্ড ব্যবহার করে আক্রমণাত্মক আপনাকে সহায়তা করতে পারে।

এবং যেমন @ লার্স অ্যান্ডরেন বলেছেন, ConcurrentHashMapবেশিরভাগ ক্ষেত্রেই সেরা পছন্দ।


4
সাম্প্রতিক হ্যাশম্যাপ আমার মতে সেরা পছন্দ। লেখক এটি জিজ্ঞাসা করেন নি, কেবল কারণেই আমি এটি সুপারিশ করিনি :) এটি সিএএস অপারেশনের কারণে কম থ্রুপুট রয়েছে, তবে সমবর্তী প্রোগ্রামিংয়ের সুবর্ণ নিয়ম হিসাবে বলেছে: "এটিকে সঠিক করুন, এবং কেবলমাত্র এটি দ্রুত তৈরি করুন ":)
ডেনিস বাজনোভ

unmodifiableMapক্লায়েন্ট মানচিত্র পরিবর্তন করতে পারবেন না তা নিশ্চিত করে। অন্তর্নিহিত মানচিত্রটি পরিবর্তিত হয়নি তা নিশ্চিত করার জন্য এটি কিছুই করে না।
পিট কিরখাম

যেমন আমি ইতিমধ্যে চিহ্নিত করেছি: "হাশম্যাপ দ্বারা নির্দেশিত বিষয়গুলিও পরিবর্তন করা উচিত নয়"
ডেনিস বাজনোভ

4

দুটি থ্রেড থেকে যথাযথ সিঙ্ক্রোনাইজেশন ছাড়াই একটি হ্যাশম্যাপটি সংশোধন করা সহজেই রেসের শর্ত হতে পারে।

  • যখন কোনও put()অভ্যন্তরীণ টেবিলটির আকার পরিবর্তন করে, এতে কিছু সময় লাগে এবং অন্য থ্রেডটি পুরানো টেবিলটিতে লিখতে থাকে।
  • put()কীগুলির হ্যাশকোডগুলি টেবিলের আকারের সমতুল্য মডুলো হলে আলাদা আলাদা কীগুলির জন্য দুটি একই বালতিটির আপডেটে নেতৃত্ব দেয়। (আসলে, হ্যাশকোড এবং বালতি সূচকের মধ্যে সম্পর্ক আরও জটিল, তবে সংঘর্ষ এখনও হতে পারে))

4
এটি কেবল বর্ণের অবস্থার চেয়ে খারাপ। HashMapআপনি যে প্রয়োগটি ব্যবহার করছেন তার অভ্যন্তরীণ উপর নির্ভর করে আপনি HashMapডেটা স্ট্রাকচারের দুর্নীতি পেতে পারেন , মেমরির বিপর্যয়ের কারণে ইত্যাদি কারণগুলি।
স্টিফেন সি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.