تفاوت بین نخ ایمن و اتمی در چیست؟


پاسخ 1:

ایمن موضوع به معنای عدم وجود مشکلی در هنگام دسترسی به چندین موضوع است. Atom به معنای غیرقابل تفکیک است ، در این زمینه مترادف با بی وقفه است.

دو روش برای اجرای قفل وجود دارد:

  1. پشتیبانی سخت افزار برای عملیات اتمی - دستورالعمل های مرکب ویژه که به طور کلی اجرا می شوند ، مانند B. Test-and-set.Be هوشمند (و پیامدهای آن را تحمل کنید) - الگوریتم پیترسون.

در مثال شما با جزئیات ، هر دو نامشخص هستند. اگر من بفهمم صحیح ، منظور شما چیزی شبیه به این است:

کلاس عمومی Unsure object اشیاء خصوصی ulock = شی جدید ()؛ عمومی int Unsafe1 دریافت کنید؛ تنظیم = 0؛ int int _unsafe2 = 0؛ عمومی int Unsafe2 get {lock (ulock) {Return _unsafe2؛ }} set {قفل (ulock) _unsafe2 = مقدار؛ }}}

کد آزمون:

var u = جدید ناامن ()؛ Parallel.For (0، 10000000، _ => {u.Unsafe1 ++؛})؛ Parallel.For (0، 10000000، _ => {u.Unsafe2 ++؛})؛ Console.WriteLine (string.Format ("{0} - {1}" ، u.Unsafe1 ، u.Unsafe2))؛

نتیجه (یکی از بسیاری از موارد ممکن):

4648265 - 4149827

در هر دو مورد ، بیش از نیمی از به روزرسانی ها ناپدید شدند.

دلیل این امر این است که ++ اتمی نیست - در واقع سه عمل جداگانه وجود دارد:

  1. مقدار را بدست آورید. 1 را به مقدار مقدار اضافه کنید.

ما می توانیم این کار را با ارائه یک عمل افزایشی که اتمی باشد برطرف کنیم. برای این کار روشهای زیادی وجود دارد ، اما در اینجا دو مورد وجود دارد:

کلاس عمومی ایمن ock slock شی ء خصوصی = شی جدید ()؛ عمومی int Safe1 {دریافت کنید؛ تنظیم } Public void SafeIncrement1 () {قفل (ulock) {this.Safe1 ++؛ } خصوصی int _safe2 = 0؛ عمومی int Safe2 get {Return _safe2؛ } set {_safe2 = مقدار؛ v} Public void SafeIncrement2 () {Interlocked.Increment (Ref _safe2)؛ }

کد آزمون:

var s = جدید ایمن ()؛ Parallel.For (0، 10000000، _ => {من SafeIncrement1 ()؛})؛ Parallel.For (0، 10000000، _ => {am SafeIncrement2 ()؛})؛ Console.WriteLine (string.Format ("{0} - {1}" ، در Safe1 ، در Safe2))؛

نتایج هر دو مورد صحیح است. حالت اول کل عملکرد کامپوزیت ++ را قفل می کند ، در حالی که دوم از پشتیبانی سخت افزاری برای عملیات اتمی استفاده می کند.

توجه داشته باشید که نوع دوم بالا با Interlocked.Increment بسیار سریعتر است ، اما در واقع از سطح پایینی برخوردار است و فقط عملکرد محدودی را ارائه می دهد. با این حال ، عملیات موجود در بسته در هم تنیده می تواند برای اجرای موارد زیر استفاده شود:

  1. قفلهای مشهور ، معروف به "موازی سازی بدبینانه" زیرا فرض می کنند که این روند قطع می شود ، تا زمانی که یک منبع مشترک به دست نیاورند ، شروع نمی شوند. هنگام مقایسه و تعویض ، از یک مقدار "قناری" ویژه ای استفاده کنید که در ابتدا ضبط کرده اید ، و سپس مطمئن شوید که در پایان هیچ چیز زیر شما تغییر نکرده است. ایده این است که موضوع دیگری قناری را از بین می برد ، بنابراین می دانید که باید معامله خود را از ابتدا تکرار کنید. این فرض می کند که کد شخصی شما اتمی است. شما نمی توانید نتایج موقت را به وضعیت اشتراکی بنویسید. شما باید کاملاً موفق باشید یا کاملاً ناکام باشید (گویی که هیچ عملیاتی انجام نداده اید).

پاسخ 2:

دو مورد کاملاً متفاوت. safe-Thread به معنای تابعی است که به گونه ای نوشته شده است که می توان آن را بارها و بارها توسط بسیاری از موضوعات مختلف فراخوانی کرد ، بدون اینکه هر نخ در عملکرد موضوع دیگر دخالت کند (مثلاً با تغییر مقدار هنگام تغییر متغیر توسط دیگری موضوع مورد استفاده قرار می گیرد).

به معنای اتمی (اگر من می دانم با آن می روید) که نمونه ای از یک شی ایجاد می شود. صرف نظر از اینکه چند بار مراجعه می شود ، این نمونه (از هر موضوع) همیشه نمایش داده می شود.


پاسخ 3:

عملیات اتمی راهی است برای دستیابی به امنیت نخی یا با استفاده از یک نوع قفل ، از قبیل قطع کنها یا سمفورها ، که از عملیات اتمی در داخل استفاده می کند ، یا با استفاده از همگام سازی بدون قفل با استفاده از نرده های اتمی و ذخیره سازی.

بنابراین عملیات اتمی بر روی انواع داده های ابتدایی ابزاری برای دستیابی به امنیت موضوع است اما به طور خودکار امنیت موضوع را تضمین نمی کند ، زیرا شما معمولاً چندین عملیات را انجام می دهید که به یکدیگر متکی هستند. شما باید اطمینان حاصل کنید که این عملیات به طور مداوم انجام می شود ، به عنوان مثال B. با صدا زدن.

بله ، نوشتن یکی از این نوع داده های اتمی در C # به صورت ایمن است ، اما این باعث نمی شود عملکرد شما در نخ استفاده شود ایمن باشد. این تنها تضمین می کند که عملیات نوشتن فرد به درستی انجام شود ، حتی اگر موضوع دوم به "همزمان" دسترسی داشته باشد. با این وجود ، دفعه بعد که از موضوع فعلی می خوانید ، اطمینان حاصل نمی شود که مقدار نوشته شده قبلی حفظ شده باشد ، زیرا ممکن است موضوع دیگری برای آن نوشته باشد ، اما فقط این مقدار خواندن معتبر است.