سؤال

هل هناك طريقة محمولة (Posix) في C للعمليات المتغيرة الذرية المشابهة لخيوط محمولة مع Pthread؟

العمليات الذرية هي عمليات مثل "الزيادة والحصول عليها" المنفذة بشكل جذري وهذا يعني أنه لا يمكن أن يتداخل تبديل السياق مع العملية. في مساحة نواة لينكس، علينا أن atomic_t. اكتب، في جافا لدينا java.util.concurrent.atomic. صفقة.

على Linux، يوفر ملف Atomic.h العمليات الذرية، ولكن تشمل المنصة تعتمد على سبيل المثال #include <asm-x86_64/atomic.h> وليس متاحا على نظام التشغيل Mac OS X بطريقة مماثلة.

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

المحلول

اعتبارا من C11 هناك اختياري المكتبة الذرية التي توفر العمليات الذرية. هذا هو محمول إلى أي منصة تحتوي على مترجم C11 (مثل GCC-4.9) مع هذه الميزة الاختيارية هذه.

يمكن التحقق من وجود الذرية مع __STDC_NO_ATOMICS__ووجود <stdatomic.h>

atomic.c.

#include <stdio.h>
#include <stdlib.h>
#ifndef __STDC_NO_ATOMICS__
#include <stdatomic.h>
#endif

int main(int argc, char**argv) {
    _Atomic int a;
    atomic_init(&a, 42);
    atomic_store(&a, 5);
    int b = atomic_load(&a);
    printf("b = %i\n", b);

    return EXIT_SUCCESS;
}

دعوات مترجم

clang -std=c11 atomic.c
gcc -std=c11 atomic.c

نصائح أخرى

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

منذ أن طلبت OS X:

(ومنذ أنه تم رفع منهجية عبر هذا الموضوع.)

نظام التشغيل X لديه وظائف OSATOMICADD32 () والأصدقاء. يتم الإعلان عنها في "/usr/include/libkern/osatomic.h". يرى دليل برمجة الخيوط, قسم "استخدام العمليات الذرية".

وليندوز، هناك interlockedincrent () والأصدقاء (انظر MSDN).

جنبا إلى جنب مع المدمجات الخليجية __nc_fetch_and_add () والأصدقاء (قد ارتبط أعلاه)، يجب أن يكون لديك شيء لكل منصة سطح المكتب الرئيسية.

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

لا، posix لا يحدد أي العمليات الحرة / الذرية المحمولة. لهذا السبب لديهم pthreads.

كنت ستحصل على استخدام طرق غير قياسية أو عصا مع ptrheads لتحويلها.

C11 الذرية الحد الأدنى من مثال Rounnable

مع إضافة خيوط في Glibc 2.28، يمكننا أن نفعل كل من الذرطيات والخيوط في C11 النقي.

مثال من: https://en.cppreference.com/w/c/language/atomic.

ج الرئيسية

#include <stdio.h>
#include <threads.h>
#include <stdatomic.h>

atomic_int acnt;
int cnt;

int f(void* thr_data)
{
    for(int n = 0; n < 1000; ++n) {
        ++cnt;
        ++acnt;
        // for this example, relaxed memory order is sufficient, e.g.
        // atomic_fetch_add_explicit(&acnt, 1, memory_order_relaxed);
    }
    return 0;
}

int main(void)
{
    thrd_t thr[10];
    for(int n = 0; n < 10; ++n)
        thrd_create(&thr[n], f, NULL);
    for(int n = 0; n < 10; ++n)
        thrd_join(thr[n], NULL);

    printf("The atomic counter is %u\n", acnt);
    printf("The non-atomic counter is %u\n", cnt);
}

ترجمة وتشغيل:

gcc -std=c11 main.c -pthread
./a.out

الإخراج المحتمل:

The atomic counter is 10000
The non-atomic counter is 8644

من المحتمل جدا أن يكون العداد غير الذرية أصغر من المرء الذري بسبب الوصول إلى المواضيع المتغيرة غير الذرية.

يمكن العثور على مثال Pthreads في: كيف أبدأ المواضيع في عادي ج؟

تم اختباره في Ubuntu 18.04 (Glibc 2.27) من خلال تجميع Glibc من المصدر: العديد من المكتبات Glibc على مضيف واحد Ubuntu 18.10 لديه Glibc 2.28 حتى يجب أن تعمل الأمور فقط هناك.

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

لا أعتقد أن هناك.

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

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