0Pricing
Ruby Academy · درس

الخيوط

التنفيذ المتزامن

الخيوط درس مجاني في Ruby Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Ruby Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Ruby Academy 4 دروس في المجموع.

ما هو الخيط؟

الخيط هو مسار مستقل للتنفيذ داخل برنامجك. تتيح لك Ruby تشغيل عدة خيوط بحيث تتداخل الأعمال زمنيًا.

  • يعمل البرنامج الرئيسي في الخيط الرئيسي.
  • تنشئ خيوطًا إضافية باستخدام Thread.new.
  • تتشارك الخيوط الذاكرة نفسها، لذا يمكنها قراءة المتغيرات نفسها وكتابتها.

تكون الخيوط مثالية عندما يقضي برنامجك وقتًا في الانتظار (للشبكة أو القرص أو السكون)، إذ يمكن لخيط أن ينتظر بينما يواصل خيط آخر العمل.

إنشاء خيط

مرّر كتلة إلى Thread.new. تُشغَّل الكتلة في خيط جديد. استدعِ join للانتظار حتى يكتمل تنفيذها قبل خروج البرنامج.

t = Thread.new do
  puts "Hello from the new thread"
end

t.join
puts "Main thread done"

أهمية join

عندما ينتهي الخيط الرئيسي، تخرج Ruby وقد لا تنتظر الخيوط الأخرى. يحجب join الخيط المستدعي حتى يكتمل الخيط المستهدف.

من دون join، قد لا تحصل الخيط العاملة على فرصة لطباعة الناتج قبل إنهاء البرنامج.

t = Thread.new do
  sleep 0.1
  puts "Worker finished"
end

puts "Waiting..."
t.join
puts "All done"

عدة خيوط في آن واحد

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

threads = (1..3).map do |n|
  Thread.new do
    puts "Thread number " + n.to_s
  end
end

threads.each(&:join)
puts "Finished all threads"

مشاركة المتغيرات

تتشارك الخيوط الذاكرة. ويكون المتغير المعرّف قبل الخيط مرئيًا داخله. هذا مفيد، لكنه قد يكون خطيرًا أيضًا إذا كتب خيطان القيمة نفسها.

counter = 0

t = Thread.new do
  counter += 1
end

t.join
puts "Counter is " + counter.to_s

حالات التسابق

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

  • تتكون counter += 1 في الواقع من قراءة ثم جمع ثم كتابة.
  • يمكن لخيطين قراءة القيمة القديمة نفسها، ثم كتابة القيمة الجديدة نفسها، مما يؤدي إلى فقدان إحدى الزيادتين.

الحل هو تنسيق الوصول باستخدام قفل.

Mutex: قفل

يضمن Mutex (الاستبعاد المتبادل) تشغيل خيط واحد فقط للتعليمات البرمجية المحمية في كل مرة. ضع القسم الحرج داخل mutex.synchronize.

mutex = Mutex.new
counter = 0

threads = (1..5).map do
  Thread.new do
    mutex.synchronize do
      counter += 1
    end
  end
end

threads.each(&:join)
puts "Counter is " + counter.to_s

إرجاع قيمة

ينتظر Thread#value انتهاء الخيط، ثم يعيد قيمة كتلته، مثل تنفيذ join تلقائيًا مع إرجاع النتيجة.

t = Thread.new do
  2 + 3
end

puts "Result is " + t.value.to_s

المتغيرات المحلية للخيوط

يمكن لكل خيط تخزين قيمه الخاصة المفهرسة برمز باستخدام Thread.current[:key]. وتبقى هذه القيم خاصة بذلك الخيط ولا تتم مشاركتها مطلقًا.

t = Thread.new do
  Thread.current[:name] = "worker"
  puts "Inside: " + Thread.current[:name]
end

t.join

معالجة الاستثناءات

إذا رفع خيط خطأً، يظل الخطأ صامتًا حتى تستدعي join أو value، وعندها يُعاد رفعه. يؤدي ضبط Thread.abort_on_exception = true إلى تعطل البرنامج بأكمله فورًا عند حدوث الأخطاء، مما يساعد في تصحيح الأخطاء.

t = Thread.new do
  raise "boom"
end

begin
  t.join
rescue => e
  puts "Caught: " + e.message
end

متى تكون الخيوط مفيدة؟

تتألق الخيوط في الأعمال المعتمدة على الإدخال والإخراج، حيث يُقضى الوقت في الانتظار. وتكون فائدتها أقل في الأعمال المعتمدة على وحدة المعالجة المركزية بسبب GVL (وسنتناوله لاحقًا).

  • مناسبة: تنزيل عناوين URL متعددة وقراءة ملفات متعددة.
  • محدودة الفائدة: إجراء حسابات عددية كثيفة عبر عدة أنوية.

احمِ دائمًا الحالة القابلة للتغيير والمشتركة باستخدام Mutex.

تحقق سريع

اختبر فهمك للخيوط.

مراجعة: الخيوط

تعلّمت أساسيات خيوط Ruby:

  • يبدأ Thread.new التنفيذ المتزامن.
  • ينتظر join، بينما ينتظر value ويعيد النتيجة.
  • تتشارك الخيوط الذاكرة، مما قد يؤدي إلى حالات التسابق.
  • يحمي Mutex مع synchronize الحالة المشتركة.
  • تتفوق الخيوط في الأعمال المعتمدة على الإدخال والإخراج.

سنستكشف بعد ذلك سبب عجز الخيوط عن الاستفادة الكاملة من عدة أنوية لوحدة المعالجة المركزية: GVL.

الأسئلة الشائعة

هل درس «الخيوط» مجاني؟

نعم — نص درس «الخيوط» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Ruby Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Ruby Academy 4 دروس في المجموع.

ماذا ستتعلم في «الخيوط»؟

التنفيذ المتزامن تتمرن على Ruby Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Ruby Academy؟

لا تُشترط خبرة سابقة. Ruby Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.

كم من الوقت يستغرق درس «الخيوط»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Ruby Academy هذا؟

نعم. كل درس في Ruby Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. الخيوط
  2. شرح GVL
  3. Fibers
  4. Ractors
← العودة إلى Ruby Academy