GNU/Linux >> Linux の 問題 >  >> Linux

Cでアトミックインクリメントとフェッチを行う方法は?

GCC はアトミック操作をサポートしています:

gcc アトミック


GCC __atomic_* ビルトイン

GCC 4.8 以降、__sync ビルトインは __atomic を支持して廃止されました ビルトイン:https://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/_005f_005fatomic-Builtins.html

それらは C++ メモリ モデルを実装し、std::atomic 内部で使用します。

次の POSIX スレッドの例は、一貫して ++ で失敗します。 x86-64 で、常に _atomic_fetch_add で動作します .

main.c

#include <assert.h>
#include <pthread.h>
#include <stdlib.h>

enum CONSTANTS {
    NUM_THREADS = 1000,
    NUM_ITERS = 1000
};

int global = 0;

void* main_thread(void *arg) {
    int i;
    for (i = 0; i < NUM_ITERS; ++i) {
        __atomic_fetch_add(&global, 1, __ATOMIC_SEQ_CST);
        /* This fails consistently. */
        /*global++*/;
    }
    return NULL;
}

int main(void) {
    int i;
    pthread_t threads[NUM_THREADS];
    for (i = 0; i < NUM_THREADS; ++i)
        pthread_create(&threads[i], NULL, main_thread, NULL);
    for (i = 0; i < NUM_THREADS; ++i)
        pthread_join(threads[i], NULL); 
    assert(global == NUM_THREADS * NUM_ITERS);
    return EXIT_SUCCESS;
}

コンパイルして実行:

gcc -std=c99 -Wall -Wextra -pedantic -o main.out ./main.c -pthread
./main.out

逆アセンブリ分析:プレーン C でスレッドを開始するにはどうすればよいですか?

Ubuntu 18.10、GCC 8.2.0、glibc 2.28 でテスト済み。

C11 _Atomic

5.1 では、上記のコードは以下で動作します:

_Atomic int global = 0;
global++;

そして C11 threads.h glibc 2.28 で追加されました。これにより、POSIX を使用せずに純粋な ANSI C でスレッドを作成できます。最小限の実行可能な例:プレーン C でスレッドを開始するにはどうすればよいですか?


Linux
  1. Gcc 4.7をインストールするにはどうすればいいですか?

  2. 方法:DRBDのレプリケーションと構成

  3. Cでアトミック変数を使用するには?

  1. LinuxとWindowsをデュアルブートする方法

  2. RHEL 7.4 に gcc 4.9.2 をインストールする方法

  3. GCC/LD で RPATH と RUNPATH を設定するには?

  1. LinuxにElasticsearchとKibanaをインストールする方法

  2. Linuxでドライブをパーティション分割してフォーマットする方法

  3. chroot jailとは何ですか?その使用方法は?