1

C++ JNI 関数 (以下に含まれる半疑似) 内では、その行に少なくとも 1 つ (場合によっては 2 つ) の追加スレッドが作成されclient_ = new VClient(&callback_)ます。私はこの関数の完了で十分だと考えましたが、どうやら次の関数 (別の JNICALL 関数) がこの後に「すぐに」呼び出されると、SEGFUALT が発生します (関数はできるだけ早く呼び出されるため、「すぐに」は引用符で囲まれています)。誰かが次のボタンを押すことができます)。new VClientが次の関数で使用されているため、Init 関数が戻り、次の関数が呼び出されるまでに の作成がまだ完了していないことが原因であるclient_と考えられます。

私はこのすべてのスレッド化ビジネスにかなり慣れていないため、これが正しい考え方であるかどうかはわかりません。私は順番にコードを実行することに慣れています。したがって、コードが行から移動するのは、client_その行のすべてが完了したためです。コードがこの行から移動し、新しいものVClientが完全に作成される前に JNI Init 関数から戻ることは可能ですか? もしそうなら、クラス/オブジェクトの作成が完了するまでこの関数を待機させるにはどうすればよいですか?

JNIEXPORT void JNICALL Java_com_ClassDir_Init(JNIEnv *env, jobject obj)
{
  LOGI("%s", __PRETTY_FUNCTION__);
  if(!client_)
  {
    LOGI("Initializing client");
    client_ = new VClient(&callback_);
    [Bunch of JNI/JAVA class and methodID lookup and saving]
  }
  else
    LOGI("Client already initialized");
}

*これcallback_は、列挙型シグナルを JNI/JAVA に送信してプログラムの進行状況を更新する処理を行うクラスです。

4

2 に答える 2

1

VClientコンストラクターがスレッドを作成するとおっしゃいました。スレッドの作成は同期プロセスですVClient。Ctorの実行は、スレッドが完全に作成され、おそらく開始されるまで続行されません。これは、VClientistanceで他のメソッド呼び出しが実行されていないためです。同期していないのは、このスタートですスレッドの。これは「完全に機能する」という意味ではなく、メインスレッドが作成されたスレッドに独自のコンテキストで実行を開始するように指示しただけです。新しいスレッドの実行ループが設定されて入力されると、(VClient構造に対して)完全に非同期になり、スレッドのスケジューリングまで実行されます。したがって、「次のJNI関数」がそのスレッドを呼び出してそこでリソースを使用しようとする場合、リソースはすでに使用可能である必要があります(つまり、新しいスレッドが使用可能になるまですでに進行していると予想されます)。そのリソースは、スレッドセーフアクセスのために保護する必要があります。

したがって、このスレッドビジネスではあまり目新しいものになる必要はありません:-)2つの重要な構成要素を調べてください。

  1. 待機条件(「ブロッキング条件変数」とも呼ばれます)。VClient ctorを呼び出した後、スレッドに渡す必要のあるオブジェクトを待ちます。スレッドは、重要な作業が終了すると条件を通知するため、最初のスレッドでの待機のブロックが解除されます。
  2. ミューテックス。複数のスレッドの実行によって同時にアクセスできるリソース(データ構造)がある場合は常に、アクセスコードの前にミューテックスをロックし、後でロックを解除する必要があります。後で到着するスレッドは、最初のスレッドが終了するまでロックをブロックします。そうしないと、2つのスレッドが同じメモリを変更しようとすると、奇妙な結果または単純なクラッシュが発生します。

これらは、OSごとおよびフレームワークごとにさまざまなAPIで異なる方法で実装されます。同じOS上の異なるフレームワークでさえ異なる傾向があります。しかし、哲学は同じです。

ところで、 「次のJNI関数」がそれを使おうとしclient_たときにスコープから外れないように宣言されているのは当然だと思います。これはおそらく、JNI実装のグローバル変数を意味します-ネイティブコードのクラスラッパーは表示されません。

于 2012-09-20T10:03:40.963 に答える
0

いいえ。'new VClient()' を呼び出すコード行は、VClient コンストラクターが終了するまで次の行に進みません。実行はシーケンシャルです。あなたの問題は他の場所にあります。

于 2012-09-19T23:17:15.500 に答える