1

これはテキスト ファイルを適切に取り込みますが、正しい順序で出力しません。生成するスレッドが 1 つ必要ですが、実装しようとしても機能しません。プログラムが実行されるたびに、yield 関数が配置されていても、誓約と短所がランダムな順序で表示されます。

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <thread>
#include <vector>
using namespace std;

void cons(string c){
//Prints consanants
cout <<"CONS:   " << c << endl;
this_thread::yield();

}

void vow(string v){
//Prints vowels
// allowing other ready threads to run
    this_thread::yield(); 
   cout <<"VOW:    " << v << endl;

}

int main() {
//Creates an array of 100
string words[100];
//Creates a starting point for i
int i = 0;
//string called x
string s;
//Takes in a file
ifstream inFile;
//Creates a vector of threads to print
vector <thread> PrintingThreads;
//Opens up the text file "phrase.txt"
inFile.open("phrase.txt");
//If It is not able to open the file
if (!inFile) {
//Display error message
   cout << "Unable to open specified file";
   //Exit with an error(1)
   exit(1); 
}
while (inFile >> s) {
words[i]=s;
i++;
}
//cycle 
for (int l=0; l<i; l++)
   {
   char first (words[l][0]);

   if ((first == 'a') || (first  == 'e') || (first  == 'i') || (first  == 'o') || (first  == 'u')||(first == 'A') || (first  == 'E') || (first  == 'I') || (first  == 'O') || (first  == 'U'))
       {
        /
       PrintingThreads.push_back(thread(vow,words[l]));

       }   


       else
       {


       PrintingThreads.push_back(thread(cons,words[l]));

       }
   }// loop with a range variable
   for (thread& t: PrintingThreads) 
       t.join();

   inFile.close();
}
4

1 に答える 1

2

次の 3 つの問題があります。

  1. を使用してスレッドの実行順序を決定することはできませんthis_thread::yield。これは、他のスレッドに優先順位を与えることを提案しながら、特定のスレッドで呼び出すことは、他のすべてのスレッドが終了するまで実行が現在のスレッドに戻らないことを保証しないためです。終了した。標準 (§30.3.2/2) によれば、実装に再スケジュールの機会を提供するだけですが、再スケジュールするかどうか、および正確にいつ再スケジュールするかを決定するのは、実行時のスレッド スケジューリング メカニズムに任されています。現在のスレッドに戻ります。

    したがって、母音で始まる行が検出されると、次のことが発生する可能性があります: a) 母音処理スレッドを開始します。b) 実行がすぐにそのスレッドに切り替わり、yieldコマンドを処理します。c) スレッドを再スケジュールする機会が実装に与えられます。 d) メイン スレッドは別の行を処理しますが、これは再び母音行になる可能性があります。e) 新しい行に対して新しいスレッドが作成されます。f)yieldコマンドが適用され、実装によって実行が再スケジュールされます。そして別のスレッドに切り替えます、 g) 実装は、最初の行のまだ未完成の母音スレッドを選択し、その母音を出力し、そのスレッドを終了します。 )、 等々。

    これは、物事が起こる可能性のある順序の 1 つにすぎません。2 番目の母音が最初の母音の前に終了するか、子音のスレッドが開始されて 2 つの母音のスレッドの前に終了するまで両方が待機することもあるかもしれません。によって順序が決まるわけではありませんyield

  2. usingyieldが現在実行中の他のすべてのスレッドが完了するまで待機することが保証されていたとしても (そうではありません!)、2 つの問題がありますスレッドを次々に作成するため、母音スレッドは待機する必要がないため、まだ存在しません。b) 一方、母音スレッドが開始されたときに存在することが保証されている唯一の他のスレッドは、メインスレッド; しかし、メイン スレッドが終了するまで母音スレッドを待たなければならない場合は、メイン スレッドjoinの最後に母音スレッドを強制的に待機させるコマンドが含まれているため、永遠に待機する必要があります。両方のスレッドが永遠のデッドロック状態でお互いを待ちます。

  3. メイン プログラムの最後でjoin、ベクトルにスレッドが挿入された順序でコマンドを実行します。したがって、yield別のスレッドがそのスレッドを待機するまでスレッドが待機すると仮定したとしても (これは完全に間違った仮定です)、子音スレッドにもステートメントが含まれjoinているため、それでも機能しません。yield結合される母音スレッドは、(文字列の元の順序で) それに続く子音スレッドが終了するまで待機する必要がありますが、joinコマンドがまだ呼び出されていないため、子音スレッドは終了しません。

母音と子音を交互に出力することを保証したい場合 (または、すべての子音行に続いてすべての母音行を出力すること) を保証する場合、最も簡単な方法は、スレッドを削除して、入力行を単純に 2 つに分割することです。配列 (またはベクトル) で、1 つは母音行用、もう 1 つは子音行用です。最後に、印刷順序を簡単に決定できます。また、以前よりも多くのメモリを消費することはありません (すべての行をwords配列に格納するとします)。

于 2012-10-16T01:41:13.267 に答える