Q1: はい、スレッドはそれ自体をキャンセルできます。ただし、これを行うと、一般的にキャンセルのすべてのマイナスの結果が生じます。おそらく代わりに使用したいと思うでしょうpthread_exit
。これはやや予測可能です。
Q2: スレッドがキャンセルされた場合、戻り値を生成できません。代わりに、その引数が指す場所pthread_join
に特別な値を置きます。残念ながら、 を呼び出す前に、特定のスレッドが (何らかの方法で)確実に終了していることを別の方法で知る必要があります。そうしないと、呼び出し元のスレッドが永久にブロックされます。nor に相当する移植可能なものはありません。(マンページには、「この機能が必要だと思われる場合は、おそらくアプリケーションの設計を再考する必要があります」と書かれているため、誰かの顔を殴りたくなりました。)PTHREAD_CANCELED
retval
pthread_join
waitpid(..., WNOHANG)
waitpid(-1, ...)
Q2a: 「スレッドのリソース」の意味によって異なります。スレッド制御ブロックとスタックの割り当てが解除されます。pthread_cleanup_push
登録されている、または実行されるすべてのデストラクタpthread_key_create
が (スレッド上で、終了する前に); 一部のランタイムは、スタック上のオブジェクトに対して C++ クラス デストラクタも実行します。スレッドが所有するすべてのリソースがこれらのメカニズムのいずれかによってカバーされるようにするのは、アプリケーション プログラマの責任です。これらのメカニズムの一部には、固有の競合状態があることに注意してください。たとえば、ファイルを開いて、それを閉じるクリーンアップをアトミック アクションとしてプッシュすることはできないため、キャンセルすると開いているファイルがリークされる可能性があります。(ファイルを開く前にクリーンアップをプッシュすることでこれを回避できるとは思わないでください。キャンセルは、システムコールが返されるたびにそれらをチェックすることです。つまり、OS がファイル記述子番号を戻り値レジスタに書き込んでから、呼び出し関数がそのレジスタをクリーンアップが期待するメモリ位置にコピーするまでの小さなギャップに到達する正確なタイミングです。となります。)
Qi: 質問していませんが、非同期キャンセルが有効になっているスレッドは、純粋な計算以外のことを公式に許可されていないことに注意してください。、、または以外のライブラリ関数を呼び出した場合の動作は未定義です。pthread_cancel
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED)
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE)