pthread_mutex_init(3)

الاسم
pthread_mutex_init, pthread_mutex_lock, pthread_mutex_trylock, pthread_mutex_unlock, pthread_mutex_destroy - عمليات على كائنات الاستبعاد المتبادل

موجز
#include <pthread.h>

pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
pthread_mutex_t errchkmutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;

int pthread_mutex_init(pthread_mutex_t *mutex,
                       const pthread_mutexattr_t *mutexattr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);

الوصف
كائن الاستبعاد المتبادل هو أداة استبعاد متبادل، وهو مفيد لحماية هياكل البيانات المشتركة من التعديلات المتزامنة، وتنفيذ المقاطع الحرجة والمراقبين.

لكائن الاستبعاد المتبادل حالتان محتملتان: غير مقفل (لا يملكه أي خيط)، ومقفل (يملكه خيط واحد). لا يمكن أبدًا أن يملك خيطان مختلفان كائن الاستبعاد المتبادل في وقت واحد. يُعلّق الخيط الذي يحاول قفل كائن استبعاد متبادل مقفل بالفعل بواسطة خيط آخر حتى يقوم الخيط المالك بفتح قفل كائن الاستبعاد المتبادل أولاً.

تُهيئ الدالة pthread_mutex_init() كائن الاستبعاد المتبادل المشار إليه بواسطة mutex وفقًا لسمات كائن الاستبعاد المتبادل المحددة في mutexattr. إذا كان mutexattr NULL، تُستخدم السمات المبدئية بدلاً من ذلك.

يدعم تطبيق LinuxThreads سمة واحدة فقط لكائن الاستبعاد المتبادل، وهي نوع كائن الاستبعاد المتبادل، والتي تكون إما "سريع" أو "استرجاعي" أو "فحص الأخطاء". يحدد نوع كائن الاستبعاد المتبادل ما إذا كان يمكن قفله مرة أخرى بواسطة خيط يملكه بالفعل. النوع المبدئي هو "سريع". راجع pthread_mutexattr_init(3) لمزيد من المعلومات حول سمات كائن الاستبعاد المتبادل.

يمكن أيضًا تهيئة المتغيرات من النوع pthread_mutex_t بشكل ثابت، باستخدام الثوابت PTHREAD_MUTEX_INITIALIZER (لكائنات الاستبعاد المتبادل السريعة)، وPTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP (لكائنات الاستبعاد المتبادل الاسترجاعية)، وPTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP (لكائنات الاستبعاد المتبادل لفحص الأخطاء).

تقفل الدالة pthread_mutex_lock() كائن الاستبعاد المتبادل المُعطى. إذا كان كائن الاستبعاد المتبادل غير مقفل حاليًا، يصبح مقفلاً ويملكه الخيط المستدعي، وتعود الدالة pthread_mutex_lock() فورًا. إذا كان كائن الاستبعاد المتبادل مقفلاً بالفعل بواسطة خيط آخر، تُعلّق الدالة pthread_mutex_lock() الخيط المستدعي حتى يُفتح قفل كائن الاستبعاد المتبادل.

إذا كان كائن الاستبعاد المتبادل مقفلاً بالفعل بواسطة الخيط المستدعي، يعتمد سلوك الدالة pthread_mutex_lock() على نوع كائن الاستبعاد المتبادل. إذا كان كائن الاستبعاد المتبادل من النوع "سريع"، يُعلّق الخيط المستدعي حتى يُفتح قفل كائن الاستبعاد المتبادل، مما يتسبب فعليًا في توقف الخيط المستدعي تامًا. إذا كان كائن الاستبعاد المتبادل من النوع "فحص الأخطاء"، تعود الدالة pthread_mutex_lock() فورًا برمز الخطأ EDEADLK. إذا كان كائن الاستبعاد المتبادل من النوع "استرجاعي"، تنجح الدالة pthread_mutex_lock() وتعود فورًا، مسجلة عدد المرات التي قام فيها الخيط المستدعي بقفل كائن الاستبعاد المتبادل. يجب تنفيذ عدد مساوٍ من عمليات pthread_mutex_unlock() قبل أن يعود كائن الاستبعاد المتبادل إلى الحالة غير المقفلة.

تتصرف الدالة pthread_mutex_trylock() بشكل مماثل للدالة pthread_mutex_lock()، باستثناء أنها لا تحجب الخيط المستدعي إذا كان كائن الاستبعاد المتبادل مقفلاً بالفعل بواسطة خيط آخر (أو بواسطة الخيط المستدعي في حالة كائن الاستبعاد المتبادل "السريع"). بدلاً من ذلك، تعود الدالة pthread_mutex_trylock() فورًا برمز الخطأ EBUSY.

تفتح الدالة pthread_mutex_unlock() قفل كائن الاستبعاد المتبادل المُعطى. يُفترض أن كائن الاستبعاد المتبادل مقفل ويملكه الخيط المستدعي عند الدخول إلى الدالة pthread_mutex_unlock(). إذا كان كائن الاستبعاد المتبادل من النوع "سريع"، تعيده الدالة pthread_mutex_unlock() دائمًا إلى الحالة غير المقفلة. إذا كان من النوع "استرجاعي"، فإنها تُنقص عدد القفل لكائن الاستبعاد المتبادل (عدد عمليات pthread_mutex_lock() التي تم تنفيذها عليه بواسطة الخيط المستدعي)، وفقط عندما يصل هذا العدد إلى الصفر يُفتح قفل كائن الاستبعاد المتبادل فعليًا.

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

تُدمر الدالة pthread_mutex_destroy() كائن استبعاد متبادل، محررة الموارد التي قد يحملها. يجب أن يكون كائن الاستبعاد المتبادل غير مقفل عند الدخول. في تطبيق LinuxThreads، لا توجد موارد مرتبطة بكائنات الاستبعاد المتبادل، وبالتالي فإن الدالة pthread_mutex_destroy() لا تفعل شيئًا فعليًا سوى التحقق من أن كائن الاستبعاد المتبادل غير مقفل.

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

سلامة الإشارة غير المتزامنة
دوال كائن الاستبعاد المتبادل ليست آمنة للإشارات غير المتزامنة. ما يعنيه هذا هو أنه لا ينبغي استدعاؤها من معالج إشارة. على وجه الخصوص، قد يتسبب استدعاء pthread_mutex_lock() أو pthread_mutex_unlock() من معالج إشارة في توقف الخيط المستدعي تامًا.

قيمة الإرجاع
تعود الدالة pthread_mutex_init() دائمًا بالقيمة 0. تعود دوال كائن الاستبعاد المتبادل الأخرى بالقيمة 0 عند النجاح ورمز خطأ غير صفري عند الخطأ.

الأخطاء
تعود الدالة pthread_mutex_lock() برمز الخطأ التالي عند الخطأ:

    EINVAL
        لم تتم تهيئة كائن الاستبعاد المتبادل بشكل صحيح.

    EDEADLK
        كائن الاستبعاد المتبادل مقفل بالفعل بواسطة الخيط المستدعي (كائنات الاستبعاد المتبادل من نوع "فحص الأخطاء" فقط).

تُرجع الدالة pthread_mutex_trylock() أكواد الخطأ التالية عند حدوث خطأ:

    EBUSY
        تعذر الحصول على المِفصل لأنه كان مقفلاً حالياً.

    EINVAL
        لم تتم تهيئة كائن الاستبعاد المتبادل بشكل صحيح.

تُرجع الدالة pthread_mutex_unlock() كود الخطأ التالي عند حدوث خطأ:

    EINVAL
        لم تتم تهيئة كائن الاستبعاد المتبادل بشكل صحيح.

    EPERM
        لا يملك الخيط المستدعي المِفصل (لمفاصل "فحص الأخطاء" فقط).

تُرجع الدالة pthread_mutex_destroy() كود الخطأ التالي عند حدوث خطأ:

    EBUSY
        المِفصل مقفل حالياً.

انظر أيضًا
pthread_mutexattr_init(3)، pthread_mutexattr_setkind_np(3)، pthread_cancel(3).

مثال
يمكن حماية متغير عام مشترك x بواسطة مِفصل كما يلي:

    int x; pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;

يجب وضع جميع الوصولات والتعديلات على x بين استدعاءات pthread_mutex_lock() و pthread_mutex_unlock() كما يلي:

    pthread_mutex_lock(&mut); /* operate on x */ pthread_mutex_unlock(&mut);

ترجمة
تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>

هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 (https://www.gnu.org/licenses/gpl-3.0.html) أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.

إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.