1. ホーム
  2. c++

[解決済み] i++はスレッドセーフでないと聞いたのですが、++iはスレッドセーフですか?

2023-02-10 04:13:38

質問

i++はスレッドセーフな文ではないと聞いたことがあります。なぜなら、アセンブリでは元の値をどこかに一時的に保存し、それをインクリメントし、それから置き換えることになり、コンテキストスイッチで中断される可能性があるからです。

しかし、私は ++i について疑問を持っています。私が知る限り、これは「add r1, r1, 1」のような単一のアセンブリ命令に還元され、それは単一の命令であるため、コンテキスト スイッチによって中断されないでしょう。

どなたか明確にしていただけませんか。私は、x86 プラットフォームが使用されていると仮定しています。

どのように解決するのですか?

聞き間違いではないか?それは、もしかしたら "i++" は特定のコンパイラや特定のプロセッサアーキテクチャではスレッドセーフですが、標準では全く義務付けられていません。実際、マルチスレッドは ISO C や C++ の標準の一部ではないので (a)

マルチスレッドは ISO C や C++ の標準の一部ではないので、コンパイル時にどのようになるかによってスレッドセーフであるかどうかを判断することはできません。

というのはかなり実現可能性が高いです。 ++i のような任意のシーケンスにコンパイルすることができます。

load r0,[i]  ; load memory into reg 0
incr r0      ; increment reg 0
stor [i],r0  ; store reg 0 back to memory

というのは、メモリインクリメント命令を持たない私の(架空の)CPUでは、スレッドセーフにならないからです。あるいは、賢く、それをコンパイルしてしまうかもしれません。

lock         ; disable task switching (interrupts)
load r0,[i]  ; load memory into reg 0
incr r0      ; increment reg 0
stor [i],r0  ; store reg 0 back to memory
unlock       ; enable task switching (interrupts)

ここで lock は無効化し unlock は割り込みを有効にします。しかし、それでも、複数の CPU がメモリを共有しているアーキテクチャでは、スレッドセーフでない可能性があります ( lock は 1 つの CPU に対してのみ割り込みを無効にすることができます)。

言語自体(または言語に組み込まれていない場合はそのためのライブラリ)がスレッドセーフな構造を提供するので、生成されるマシンコードの理解(またはおそらく誤解)に依存するのではなく、それらを使用する必要があります。

Java のようなもの synchronizedpthread_mutex_lock() (一部のOSではC/C++で利用可能)を調べる必要があるのは (a) .


(a) この質問は、C11 および C++11 標準が完成する前に投げかけられたものです。これらの反復により、現在では原子データ型を含む言語仕様にスレッドのサポートが導入されています (ただし、原子データ型と一般的なスレッドは オプションです。 少なくとも C では)。