স্টাড :: শেয়ার্ড_পিটার থ্রেড সুরক্ষা ব্যাখ্যা করা হয়েছে


106

আমি http://gcc.gnu.org/onlinesocs/libstdc++/manual/shared_ptr.html পড়ছি এবং কিছু থ্রেড সুরক্ষা বিষয়গুলি এখনও আমার কাছে পরিষ্কার নয়:

  1. স্ট্যান্ডার্ড গ্যারান্টি দেয় যে রেফারেন্স গণনা থ্রেড হ্যান্ডলড নিরাপদ এবং এটি প্ল্যাটফর্মটি স্বাধীন, তাই না?
  2. অনুরূপ ইস্যু - স্ট্যান্ডার্ড গ্যারান্টি দেয় যে কেবল একটি থ্রেড (সর্বশেষ রেফারেন্স ধারণ করে) ভাগ করা বস্তুটিতে ডিলিট কল করবে, তাই না?
  3. শেয়ারড_পিটার এতে থাকা সামগ্রীর জন্য কোনও থ্রেড সুরক্ষার গ্যারান্টি দেয় না?

সম্পাদনা করুন:

সুডোকোড:

// Thread I
shared_ptr<A> a (new A (1));

// Thread II
shared_ptr<A> b (a);

// Thread III
shared_ptr<A> c (a);

// Thread IV
shared_ptr<A> d (a);

d.reset (new A (10));

চতুর্থ থ্রেডে রিসেট () কল করা কি প্রথম থ্রেডে তৈরি হওয়া একটি শ্রেণির পূর্ববর্তী উদাহরণ মুছবে এবং এটিকে নতুন উদাহরণের সাথে প্রতিস্থাপন করবে? তাছাড়া আইভি থ্রেডে রিসেট () কল করার পরে অন্যান্য থ্রেডগুলি কেবল নতুন নির্মিত বস্তুটি দেখতে পাবে?


24
ডান, ডান এবং ঠিক।
spraff

16
আপনার make_sharedপরিবর্তেnew
qdii

উত্তর:


87

অন্যরা যেমন উল্লেখ করেছে, আপনি এটি আপনার মূল 3 টি প্রশ্ন সম্পর্কে সঠিকভাবে খুঁজে পেয়েছেন।

তবে আপনার সম্পাদনার শেষ অংশ

চতুর্থ থ্রেডে রিসেট () কল করা কি প্রথম থ্রেডে তৈরি হওয়া একটি শ্রেণির পূর্ববর্তী উদাহরণ মুছবে এবং এটিকে নতুন উদাহরণের সাথে প্রতিস্থাপন করবে? তাছাড়া আইভি থ্রেডে রিসেট () কল করার পরে অন্যান্য থ্রেডগুলি কেবল নতুন নির্মিত বস্তুটি দেখতে পাবে?

ভুল. শুধু dনতুন নির্দেশ করবে A(10), এবং a, bএবং cমূল বিন্দু চলতে থাকবে A(1)। এটি নিম্নলিখিত সংক্ষিপ্ত উদাহরণে পরিষ্কারভাবে দেখা যায় can

#include <memory>
#include <iostream>
using namespace std;

struct A
{
  int a;
  A(int a) : a(a) {}
};

int main(int argc, char **argv)
{
  shared_ptr<A> a(new A(1));
  shared_ptr<A> b(a), c(a), d(a);

  cout << "a: " << a->a << "\tb: " << b->a
     << "\tc: " << c->a << "\td: " << d->a << endl;

  d.reset(new A(10));

  cout << "a: " << a->a << "\tb: " << b->a
     << "\tc: " << c->a << "\td: " << d->a << endl;
                                                                                                                 
  return 0;                                                                                                          
}

(স্পষ্টতই, আমি কোনও থ্রেডিং নিয়ে বিরক্ত করি নি: এটি shared_ptr::reset()আচরণের কারণ নয় ))

এই কোড আউটপুট হয়

এ: 1 বি: 1 সি: 1 ডি: 1

এ: 1 বি: 1 সি: 1 ডি: 10


35
  1. সঠিক, shared_ptrএকটি রেফারেন্স গণনা মানের পারমাণবিক বৃদ্ধি / হ্রাস ব্যবহার করুন।

  2. স্ট্যান্ডার্ড গ্যারান্টি দেয় শুধুমাত্র একটি থ্রেড একটি ভাগ করা অবজেক্টে মুছুন অপারেটর কল করবে। আমি নিশ্চিত নই যে এটি ভাগ করে নেওয়া পয়েন্টারটির অনুলিপিটি মুছে ফেলা শেষ থ্রেডটি নির্দিষ্ট করে কিনা তা কলটিকে মুছে ফেলা হবে (সম্ভবত বাস্তবে এটি কেস হবে)।

  3. না তারা করেন না, এতে সঞ্চিত বস্তুটি এক সাথে একাধিক থ্রেড দ্বারা সম্পাদনা করা যেতে পারে।

সম্পাদনা করুন: একটু ফলোআপ, কেমন ভাগ পয়েন্টার সাধারণভাবে কাজ একটি ধারণা আপনি তাকান করতে চাইবেন পেতে চাইলে দয়া boost::shared_ptrউৎস: http://www.boost.org/doc/libs/1_37_0/boost/shared_ptr.hpp


3
1. আপনি যখন বলছেন "'শেয়ারড_প্টারস' একটি রেফারেন্স গণনা মানের পারমাণবিক বৃদ্ধি / হ্রাস ব্যবহার করে।" আপনার অর্থ কি তারা পারমাণবিক বৃদ্ধি / হ্রাসের জন্য কোনও অভ্যন্তরীণ লক ব্যবহার করেন না, যা প্রসঙ্গে স্যুইচ করে? সহজ ভাষায় লক ব্যবহার না করে একাধিক থ্রেড কি বৃদ্ধি / হ্রাস রেফারেন্স গণনা করতে পারে? একটি পারমাণবিক বর্ধন বিশেষ পারমানবিক_পৃষ্ঠা_স্যাপা / অ্যাটমিক_টেষ্ট_আর_সংশ্লিষ্ট নির্দেশাবলী দ্বারা সম্পন্ন হয়?
rahul.deshmukhpatil

@ আরহুল সংকলকটি একটি মুটেক্স / লক ব্যবহারের জন্য নিখরচায়, তবে বেশিরভাগ ভাল সংকলক প্ল্যাটফর্মগুলিতে যেখানে একটি লক-মুক্ত করা যায় সেখানে একটি মুটেক্স / লক ব্যবহার করবেন না।
বার্নার্ড

@ বার্নার্ড: আপনি কি বোঝাতে চেয়েছেন যে এটি প্ল্যাটফর্মের জন্য "সংকলকদের স্টাড লাইব শেয়ারড_পিটার" প্রয়োগের উপর নির্ভর করে?
rahul.deshmukhpatil

2
হ্যাঁ. আমার বোধগম্যতা থেকে, মানকটি এটি লক-মুক্ত হতে হবে তা বলে না। তবে সর্বশেষতম জিসিসি এবং এমএসভিসিতে এটি ইন্টেল x86 হার্ডওয়্যারটিতে লক-ফ্রি, এবং আমি মনে করি যে হার্ডওয়্যার যখন এটি সমর্থন করে তখন অন্যান্য ভাল সংকলকরাও এটি করতে পারে।
বার্নার্ড

18

std::shared_ptr থ্রেড নিরাপদ নয়।

একটি ভাগ করা পয়েন্টার হ'ল দুটি পয়েন্টার যুক্ত, একটিতে বস্তুর সাথে একটি এবং একটি নিয়ন্ত্রণ ব্লকের (রেফ কাউন্টারটি ধারণ করে, দুর্বল পয়েন্টারগুলির লিঙ্কগুলি ...)।

একাধিক স্ট্যান্ড :: শেয়ারড_পিটার থাকতে পারে এবং যখনই তারা রেফারেন্স কাউন্টারটি পরিবর্তন করতে নিয়ন্ত্রণ ব্লক অ্যাক্সেস করে এটি থ্রেড-নিরাপদ তবে std::shared_ptrনিজেই থ্রেড-নিরাপদ বা পারমাণবিক নয়।

যদি আপনি কোনও নতুন অবজেক্টটিকে std::shared_ptrকিছুক্ষণ নির্দিষ্ট করে দেন অন্য থ্রেড এটি ব্যবহার করে তবে এটি নতুন অবজেক্ট পয়েন্টারটির সাথে শেষ হতে পারে তবে এটি পুরানো অবজেক্ট => ক্র্যাশের নিয়ন্ত্রণ ব্লকে একটি পয়েন্টার ব্যবহার করছে।


4
আমরা বলতে পারি যে একক std::shared_ptrউদাহরণ থ্রেড নিরাপদ নয়। স্ট্যান্ড :: শেয়ার্ড_পিটার রেফারেন্স থেকে:If multiple threads of execution access the same shared_ptr without synchronization and any of those accesses uses a non-const member function of shared_ptr then a data race will occur;
জে কোভালস্কি

এটি আরও ভাল বলা যেতে পারে। std::shared_ptr<T>যখন থ্রেড সীমানা জুড়ে সর্বদা মান দ্বারা অনুলিপি করা হয় (অনুলিপি / সরানো) তখন একটি উদাহরণ গ্যারান্টিযুক্ত থ্রেড-নিরাপদ । অন্যান্য সমস্ত ব্যবহার, std::shared_ptr<T>&থ্রেডের সীমানা
ছাড়াই
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.