مشكلة المنتج/المستهلك المتعدد ورمز القسم الحرج
-
05-07-2019 - |
سؤال
أحاول حل مشكلة منتج/مستهلك متعدد في لغة C، لكنها لا تعمل كما هو متوقع.فيما يلي بعض التعليمات البرمجية الزائفة لتمثيل التنفيذ الخاص بي.
Thread thread1;
Thread thread2;
Thread thread3;
Data data1;
Mutex data1_mutex;
Semaphore data1_empty;
Semaphore data1_fill;
Data data2;
Mutex data2_mutex;
Semaphore data2_empty;
Semaphore data2_fill;
thread1()
{
// creates data and places it into data1.
wait(data1_empty);
lock(data1_mutex);
// critical section
unlock(data1_mutex);
post(data1_fill);
}
thread2()
{
// Removes data from data1, processes it, and places it into data2.
// data1
wait(data1_fill);
lock(data1_mutex);
// data2
wait(data2_empty);
lock(data2_mutex);
// critical section
// data2
unlock(data2_mutex);
post(data2_fill);
// data1
unlock(data1_mutex);
post(data1_empty);
}
thread3()
{
// Removes data from data2, prints its results, and removes it.
wait(data2_fill);
lock(data2_mutex);
// critical section
unlock(data2_mutex);
post(data2_empty);
}
ومع ذلك، مع هذا الحل، سوف تمتلئ البيانات 1، ولكن سيتم قفل مؤشر الترابط 2 ولن يعمل أبدًا.هل هناك خطأ ما في تنفيذي؟
تحرير رقم 1
إحدى المشكلات التي وجدتها هي أن كائن المزامنة الثاني الخاص بي لم يتم إنشاؤه بشكل صحيح.لا أعرف ما هو الخطأ في ذلك، لذلك أنا فقط أستخدم كائن المزامنة الأول لجميع سلاسل الرسائل.هناك أيضًا شيء آخر قمت به لتشغيله، لذا سأقوم بتحديث الكود الزائف الخاص بي ليعكس ذلك لاحقًا عندما يكون لدي دقيقة.
المحلول
تأكد من قمت بنشر data1_empty
وdata2_empty
في البداية.
نصائح أخرى
إذا كنت تستخدم نوعا من الاصطفاف نوع لData
، يجب أن تكون قادرة على إزالة الإشارات "فارغة" تماما، إلا إذا كنت تحاول فرض شرط أن كل عمق طابور Data
بدقة 0 أو 1. إذا كنت تستخدم متغير محلي في thread2
، يمكنك تقليل حجم مقطع حرج.
والتعليمة البرمجية ثم يصبح شيئا من هذا القبيل:
thread1() {
//Wait for data to put in the queue (i.e. a blocking socket read)
lock(data1_mutex);
data1.push(someData);
unlock(data1_mutex);
post(data1_fill);
}
thread2() {
DataType dataElement;
wait(data1_fill);
lock(data1_mutex);
dataElement = data1.pop();
unlock(data1_mutex);
lock(data2_mutex);
data2.push(dataElement);
unlock(data2_mutex);
post(data2_fill);
}
thread3() {
DataType dataElement;
wait(data2_fill);
lock(data2_mutex);
dataElement = data2.pop();
unlock(data2_mutex);
//do something with dataElement here
}
ما قاله wrang-wrang، وحاول عدم الضغط على قفل data_1 أثناء انتظار data_2_empty.يمكنك تحقيق ذلك عن طريق الاحتفاظ بمخزن مؤقت بديل لـ data_1 وdata_2 الذي يمكنك تبديله.يقوم Thread_2 بتبديل data_1 أثناء معالجته إلى data_2، ويقوم Thread_3 بتبديل data_2 أثناء معالجته.سيسمح الكود الزائف الحالي الخاص بك بتشغيل الخيط 1 والخيط 3 بشكل متزامن، لكنه لن يسمح بتنفيذ الخيط 2 في نفس الوقت مثل أي من الخيطين الآخرين.