سؤال

هذا مجرد سيناريو افتراضي لتوضيح سؤالي. لنفترض أن هناك خيطان و TVAR واحد مشترك بينهما. يوجد في موضوع واحد كتلة ذرية تقرأ TVAR وتستغرق 10s لإكمالها. في خيط آخر عبارة عن كتلة ذرية تعدل TVAR كل ثانية. هل ستكتمل أول حظر ذري على الإطلاق؟ من المؤكد أنه سيستمر في العودة إلى البداية ، لأن السجل دائمًا في حالة غير متناسقة؟

هل كانت مفيدة؟

المحلول

كما قال آخرون: من الناحية النظرية ، لا يوجد ضمان للتقدم. في الممارسة العملية ، لا يوجد أيضًا ضمان للتقدم:

import Control.Monad -- not needed, but cleans some things up
import Control.Monad.STM
import Control.Concurrent.STM
import Control.Concurrent
import GHC.Conc
import System.IO

main = do
    tv <- newTVarIO 0
    forkIO (f tv)
    g tv

f :: TVar Int -> IO ()
f tv = forever $ do
    atomically $ do
            n <- readTVar tv
            writeTVar tv (n + 1)
            unsafeIOToSTM (threadDelay 100000)
    putStr "."
    hFlush stdout

g :: TVar Int -> IO ()
g tv = forever $ do
    atomically $ do
            n <- readTVar tv
            writeTVar tv (n + 1)
            unsafeIOToSTM (threadDelay 1000000)
    putStrLn "Done with long STM"

ما سبق لا يقول "تم القيام به مع Long STM" في اختباراتي.

من الواضح أنه إذا كنت تعتقد أن الحساب لا يزال ساري المفعول/ذي الصلة ، فأنت تريد أيضًا

  1. اترك الكتلة الذرية ، وأداء حساب باهظ الثمن ، وأدخل الافتراضات الذرية / تأكيد الافتراضات صالحة / وتحديث القيمة. يحتمل أن يكون خطيرًا ، ولكن ليس أكثر من معظم استراتيجيات القفل.
  2. مذكرات النتائج في الكتلة الذرية ، وبالتالي فإن النتيجة الصالحة لن تكون أكثر من مجرد بحث رخيص بعد إعادة المحاولة.

نصائح أخرى

يمنع STM Deadlock ، لكنه لا يزال عرضة للجوع. من الممكن في حالة مرضية للعمل الذري 1S أن يطالب المورد دائمًا.

ومع ذلك ، فإن التغييرات في هذا الحدوث نادرة جدًا - لا أعتقد أنني رأيتها في الممارسة العملية.

من أجل الدلالات ، انظر معاملات الذاكرة القابلة للتأليف, ، القسم 6.5 "التقدم". تضمن STM في Haskell فقط أن المعاملة الجارية سترتكب بنجاح (أي عدم وجود طريق مسدود) ، ولكن في أسوأ الحالات ، ستمنع معاملة غير محدودة الآخرين.

لا ، سوف يعمل بشكل جيد. بالضبط كيف يتفاعل الخيط اثنين يعتمد على منطق إعادة المحاولة.

على سبيل المثال ، لنفترض أن لديك:

ten tv = do
  n <- readTVar tv
  when (n < 7) retry
  writeTVar tv 0
  -- do something that takes about 10 seconds

one tv = do
  modifyTVar tv (+1)
  -- do something that takes about 1 second

لذلك "ten"سيكون الخيط في حالة إعادة المحاولة حتى يصل tvar إلى القيمة 7 ، ثم سيستمر.

لاحظ أنه لا يمكنك التحكم بشكل مباشر في المدة التي ستستغرقها هذه الحسابات داخل موناد STM. سيكون ذلك بمثابة تأثير جانبي ، ولا يُسمح بالآثار الجانبية في حسابات STM. الطريقة الوحيدة للتواصل مع العالم الخارجي هي عبر القيم التي يتم تمريرها من خلال ذاكرة المعاملات.

وهذا يعني أنه إذا كان المنطق "الذي يمرر" من خلال ذاكرة المعاملات صحيحًا ، فسيعمل البرنامج بشكل مستقل بشكل مستقل عن الوقت المحدد للوقت الذي يستغرقه أي جزء منه. هذا جزء من ضمان STM.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top