هاسكل المتزامنة

هاسكل المتزامن (أو Control.Concurrent ، أو هاسكل المتزامن والمتوازي ) هو امتداد للغة البرمجة الوظيفية هاسكل ، يضيف أنواع بيانات أولية صريحة للتزامن . [ 1 ] أُضيف لأول مرة إلى هاسكل 98 ، وأصبح منذ ذلك الحين مكتبة مضمنة كجزء من مُصرّف غلاسكو هاسكل .Control.Concurrent

مفهوماها الأساسيان هما:

تم بناء مجموعة من التجريدات المفيدة للتزامن والتزامن [ 2 ] مثل القنوات غير المحدودة ، والإشارات ، ومتغيرات العينة على هذا الأساس .

تتميز خيوط هاسكل بانخفاض الحمل الزائد: فعمليات الإنشاء، وتبديل السياق، والجدولة كلها عمليات داخلية في نظام تشغيل هاسكل . يتم ربط هذه الخيوط على مستوى هاسكل بعدد قابل للتكوين من خيوط نظام التشغيل ، وعادةً ما يكون خيط واحد لكل نواة معالج .

ذاكرة المعاملات البرمجية

يُعيد امتداد ذاكرة المعاملات البرمجية ( STM) [ 3 ] لمترجم غلاسكو هاسكل (GHC) استخدام بدائيات تفرع العمليات الخاصة بـ Concurrent Haskell. ومع ذلك، فإن STM:

موناد STM

تُعدّ موناد STM [ 4 ] تطبيقًا لذاكرة المعاملات البرمجية في لغة هاسكل. وهي مُطبّقة في GHC، وتسمح بتعديل المتغيرات القابلة للتغيير في المعاملات .

النهج التقليدي

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

نوع الحساب = IORef عدد صحيحتحويل :: عدد صحيح -> حساب -> حساب -> إدخال/ إخراج () تحويل المبلغ من إلى = do fromVal <- readIORef from -- (A) toVal <- readIORef to writeIORef from ( fromVal - amount ) writeIORef to ( toVal + amount )

يُسبب هذا مشاكل في الحالات المتزامنة حيث قد تتم عمليات تحويل متعددة على نفس الحساب في الوقت نفسه . فإذا كانت هناك عمليتا تحويل تسحبان أموالاً من حساب from، وتم تنفيذ كلتيهما (A)قبل أن تُسجل أي منهما قيمتها الجديدة، فمن المحتمل أن تُضاف الأموال إلى الحسابين الآخرين، بينما تُسحب قيمة واحدة فقط من المبلغ المحوّل من الحساب from، مما يُؤدي إلى حالة تضارب . وهذا بدوره يُؤدي إلى حالة غير متناسقة في تطبيق الخدمات المصرفية.

يُعدّ التأمين حلاً تقليدياً لمثل هذه المشكلة. على سبيل المثال، يمكن وضع أقفال حول التعديلات التي تُجرى على حساب ما لضمان حدوث عمليات الإيداع والسحب بشكل ذري. في لغة هاسكل، يتم تحقيق التأمين باستخدام متغيرات MVars.

نوع الحساب = عدد صحيح MVarcredit :: Integer -> Account -> IO () credit amount account = do current <- takeMVar account putMVar account ( current + amount )debit :: Integer -> Account -> IO () debit amount account = do current <- takeMVar account putMVar account ( current - amount )

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

تحويل :: عدد صحيح -> حساب -> حساب -> إدخال/إخراج () تحويل المبلغ من إلى = قم بخصم المبلغ من من ودائن المبلغ إلى

لا تزال حالة التزامن قائمة: قد يتم خصم المبلغ من الحساب الأول، ثم قد يتم تعليق تنفيذ العملية، مما يترك الحسابات ككل في حالة غير متناسقة. لذا، يجب إضافة أقفال إضافية لضمان صحة العمليات المركبة، وفي أسوأ الأحوال، قد يكون من الضروري قفل جميع الحسابات بغض النظر عن عددها المستخدم في عملية معينة.

المعاملات الذرية

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

نوع الحساب = عدد صحيح متغيرcredit :: Integer -> Account -> STM () credit amount account = do current <- readTVar account writeTVar account ( current + amount )مدين :: عدد صحيح -> حساب -> STM () مدين المبلغ الحساب = do الحالي <- قراءة متغير الحساب كتابة متغير الحساب ( الحالي - المبلغ )تحويل :: عدد صحيح -> حساب -> حساب -> STM () تحويل المبلغ من إلى = قم بخصم المبلغ من من ودائن المبلغ إلى

يمكن اعتبار أنواع الإرجاع STM ()مؤشرًا على أننا نقوم بكتابة نصوص برمجية للمعاملات. عند تنفيذ المعاملة فعليًا، تُستخدم دالة. يضمن التنفيذ المذكور أعلاه عدم تداخل أي معاملات أخرى مع المتغيرات المستخدمة (من وإلى) أثناء التنفيذ، مما يسمح للمطور بالتأكد من عدم حدوث حالات تضارب في البيانات. يمكن إجراء المزيد من التحسينات لضمان الحفاظ على منطق العمل في النظام، أي ألا تحاول المعاملة سحب الأموال من حساب ما إلا بعد توفر رصيد كافٍ فيه.atomically :: STM a -> IO a

تحويل :: عدد صحيح -> حساب -> حساب -> STM () تحويل المبلغ من إلى = do fromVal <- readTVar from if ( fromVal - amount ) >= 0 then do debit amount from credit amount to else retry

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

قد يبدو برنامج نموذجي يستخدم دالة التحويل كما يلي:

الوحدة الرئيسية حيثاستيراد Control.Concurrent ( forkIO ) استيراد Control.Concurrent.STM استيراد Control.Monad ( forever ) استيراد System.Exit ( exitSuccess )نوع الحساب = عدد صحيح متغيرmain = do bob <- newAccount 10000 jill <- newAccount 4000 repeatIO 2000 $ forkIO $ atomically $ transfer 1 bob jill forever $ do bobBalance <- atomically $ readTVar bob jillBalance <- atomically $ readTVar jill putStrLn ( "رصيد بوب: " ++ show bobBalance ++ ", رصيد جيل: " ++ show jillBalance ) if bobBalance == 8000 then exitSuccess else putStrLn "جارٍ المحاولة مرة أخرى."repeatIO :: Integer -> IO a -> IO a repeatIO 1 m = m repeatIO n m = m >> repeatIO ( n - 1 ) mnewAccount :: Integer -> IO Account newAccount amount = newTVarIO amountتحويل :: عدد صحيح -> حساب -> حساب -> STM () تحويل المبلغ من إلى = do fromVal <- readTVar from if ( fromVal - amount ) >= 0 then do debit amount from credit amount to else retrycredit :: Integer -> Account -> STM () credit amount account = do current <- readTVar account writeTVar account ( current + amount )مدين :: عدد صحيح -> حساب -> STM () مدين المبلغ الحساب = do الحالي <- قراءة متغير الحساب كتابة متغير الحساب ( الحالي - المبلغ )

والذي من المفترض أن يطبع "رصيد بوب: 8000، رصيد جيل: 6000". هنا atomicallyتم استخدام الدالة لتشغيل إجراءات STM في موناد الإدخال/الإخراج.

مراجع

  1. بيتون جونز، سيمون ؛ جوردون، أندرو د .؛ فين، سيغبيورن (1 يناير 1996). كُتب في شاطئ بيترسبيرغ، فلوريدا. هاسكل المتزامنة . ندوة ACM SIGPLAN-SIGACT حول مبادئ لغات البرمجة (PoPL). نيويورك، نيويورك: رابطة آلات الحوسبة (ACM). ISBN 978-0-89791-769-8.(بعض الأقسام قديمة فيما يتعلق بالتطبيقات اللاحقة.)
  2. مكتبات هاسكل الهرمية ، Control.Concurrent ، مؤرشفة بتاريخ 2014-11-06 (عدم تطابق التاريخ) في Wayback Machine
  3. تيم هاريس، سيمون مارلو ، سيمون بيتون جونز ، وموريس هيرليهي . معاملات الذاكرة القابلة للتركيب . ندوة ACM حول مبادئ وممارسات البرمجة المتوازية 2005 (PPoPP'05). 2005.
  4. التحكم.التزامن.STM