هل يمكن لـ pthreads مشاركة الموارد العالمية فقط؟

StackOverflow https://stackoverflow.com/questions/1420140

  •  07-07-2019
  •  | 
  •  

سؤال

أحاول مشاركة البنية بين موضوعين لا متغير عالمي.يتم إنشاء مثيل للمتغير نفسه على المكدس في الوظيفة الرئيسية، ثم يتم تمرير المؤشر الخاص به كمعلمة إلى كلا الخيطين عند بدء تشغيل كلا الخيطين.

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

هذا كله لأنني أريد تجنب إضافة متغيرات عامة لصيانة التعليمات البرمجية.

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

المحلول

وتذكر أن المواضيع الحصول على كومة الخاصة بهم - حتى إذا كنت تمرير عدد صحيح في وظيفة يخرج من نطاق، كنت في اشارة الى الذاكرة التي تحمل الآن شيء مختلف تماما

void foo(void)
{
    pthread_t t1, t2;
    struct foo common_value;

    if (pthread_create(&t1, NULL, a, &common_value) != 0)
    {
        return -1;
    }    

    if (pthread_create(&t2, NULL, b, &common_value) != 0)
    {
        return -1;
    }    

    // upon exiting this function, common_value is no longer what you think it is!
}

نصائح أخرى

وأنا لا أتكلم عن التظاهر في الأناقة، ولكن يبدو أن هذا العمل بالنسبة لي على ماك X 10.5.8.

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

static void *writer(void *arg)
{
    int * volatile i = arg;

    for (*i = 1; *i < 10; (*i)++)
    {
        printf("writer(): pseudo_global = %d\n", *i);
        fflush(stdout);
        sleep(1);
    }
    printf("writer(): pseudo_global = %d (exiting)\n", *i);
    fflush(stdout);
    return(0);
}

static void *reader(void *arg)
{
    int * volatile i = arg;
    while (*i < 10)
    {
        printf("reader(): pseudo_global = %d\n", *i);
        fflush(stdout);
        sleep(1);
    }
    printf("reader(): pseudo_global = %d (exiting)\n", *i);
    fflush(stdout);
    exit(0);
}

int main(void)
{
    volatile int pseudo_global = 0;
    pthread_t t1;
    pthread_t t2;
    if (pthread_create(&t1, 0, writer, &pseudo_global) != 0)
    {
        perror("pthread_create() for thread 1");
        exit(1);
    }
    if (pthread_create(&t2, 0, reader, &pseudo_global) != 0)
    {
        perror("pthread_create() for thread 1");
        exit(1);
    }
    while (pseudo_global < 10)
    {
        printf("main():   pseudo_global = %d\n", pseudo_global);
        fflush(stdout);
        sleep(1);
    }
    printf("main():   pseudo_global = %d (exiting)\n", pseudo_global);
    fflush(stdout);
    return(0);
}

لاحظ أن أضع تصفيات "متقلبة" إلى رمز لل"تأكد"، ولكن بصرف النظر عن انتزاع تحذيرات حول تصفيات التخلص منها في المكالمات pthread_create()، فإنه لم يحدث أي فارق كبير. ركضت أيضا رمز من دون أي تصفيات volatile دون مشكلة.

وهذا الرمز يدل، كما أعتقد، أنه في تطبيق واحد على الأقل المواضيع POSIX، يمكنك مشاركة الواقع المتغير المحلي على كومة من وظيفة لم خرجت في حين أن المواضيع قيد التشغيل.

وأنا على استعداد للاعتقاد يجب أن أكون أكثر حذرا بشأن إنهاء موضوع ويجب أن نتأكد من أن main() لا خروج بدون استخدام pthread_join() للتأكد من أن المواضيع التي خرجت لأول مرة.

والناتج مثال:

$ make ptex
gcc -O ptex.c -o ptex  
ptex.c: In function ‘main’:
ptex.c:40: warning: passing argument 4 of ‘pthread_create’ discards qualifiers from pointer target type
ptex.c:45: warning: passing argument 4 of ‘pthread_create’ discards qualifiers from pointer target type
$ ./ptex
writer(): pseudo_global = 1
main():   pseudo_global = 0
reader(): pseudo_global = 1
writer(): pseudo_global = 2
main():   pseudo_global = 2
reader(): pseudo_global = 2
writer(): pseudo_global = 3
main():   pseudo_global = 3
reader(): pseudo_global = 3
writer(): pseudo_global = 4
main():   pseudo_global = 4
reader(): pseudo_global = 4
writer(): pseudo_global = 5
reader(): pseudo_global = 5
main():   pseudo_global = 5
writer(): pseudo_global = 6
reader(): pseudo_global = 6
main():   pseudo_global = 6
writer(): pseudo_global = 7
reader(): pseudo_global = 7
main():   pseudo_global = 7
writer(): pseudo_global = 8
reader(): pseudo_global = 8
main():   pseudo_global = 8
writer(): pseudo_global = 9
reader(): pseudo_global = 9
main():   pseudo_global = 9
writer(): pseudo_global = 10 (exiting)
reader(): pseudo_global = 10 (exiting)
main():   pseudo_global = 10 (exiting)
$

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

وبمجرد الانتهاء من التحقق أن الرجاء نشر بعض الأمثلة رمز بسيط يوضح مشكلتك أن الآخرين يمكن اختبار.

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

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

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