Cには、pthreadを使用したポータブルスレッドに類似したアトミック変数操作用の(POSIX-)移植可能な方法はありますか?
アトミック操作は、アトミックに実行される「インクリメントとゲット」のような操作です。つまり、コンテキストスイッチが操作に干渉することはありません。 Linuxカーネルスペースでは、 atomic_t タイプ、Javaには Java.util.concurrent.atomic パッケージが必要です。
Linuxでは、atomic.hファイルはアトミック操作を提供しますが、インクルードはプラットフォームに依存します。 #include <asm-x86_64/atomic.h>
と同様に、Mac OS Xでは使用できません。
C11以降、アトミック操作を提供するオプションの Atomic library があります。これは、このオプション機能を備えた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アトミックはこれを行うための最良の方法です-私はそれらがGCC 4.9に含まれると信じています。
OS Xを要求してから:
(そして、このスレッドでクロスプラットフォーム性が引き上げられて以来。)
OS Xには関数OSAtomicAdd32()とその友達がいます。 「/usr/include/libkern/OSAtomic.h」で宣言されています。 スレッディングプログラミングガイド のセクション「アトミック操作の使用」を参照してください。
Windowsの場合、InterlockedIncrement()とその仲間(MSDNを参照)があります。
Gccビルトイン__ sync_fetch_and_add()および友達(上記にリンクされています)とともに、すべてのメインデスクトッププラットフォームに何かが必要です。
私はまだ自分で使用していませんが、数日中に使用する可能性があることに注意してください。
いいえ、POSIXはanyポータブルロックフリー/アトミック操作を指定していません。それがpthreadを持っている理由です。
非標準的な方法を使用するか、移植性のためにptrheadを使用する必要があります。
C11アトミック最小実行可能例
Glibc 2.28にスレッドを追加すると、純粋なC11でアトミックとスレッドの両方を実行できます。
例: https://en.cppreference.com/w/c/language/atomic
main.c
#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
非アトミック変数へのスレッド間のきちんとしたアクセスのため、非アトミックカウンターはアトミックカウンターよりも小さい可能性が非常に高いです。
Pthreadの例は次の場所にあります: プレーンCでスレッドを開始するにはどうすればよいですか?
ソースからglibcをコンパイルすることにより、Ubuntu 18.04(glibc 2.27)でテストされています: 単一のホスト上の複数のglibcライブラリ Ubuntu 18.10にはglibc 2.28があるため、そこでうまくいくはずです。
AFAIKには、アトミック操作を実行するためのクロスプラットフォームの方法はありません。そこに図書館があるかもしれませんが、私は知りません。自分でロールするのは特に難しいことではありません。
あるとは思いません。
それを解決する1つの方法は、もちろん許可するライセンスです。たとえば、関連するアーキテクチャごとの実装をコピーします。 Linuxカーネル空間。私はこれらのプリミティブの進化を厳密には追跡していませんが、それらが実際にプリミティブであること、つまり、カーネル内の他のサービスやAPIに依存していないことを推測します。