0

私は C++ 初心者で、Pthread および Ncurses ライブラリを使用しようとしています。端末画面に飛んでくるボールを表示するプログラムを作っています。Ball クラスを作成しました。

ファイル内で Ball.h 宣言、Ball.c 実装内。Ball.h :

class Ball {

public:
//ATTRIBUTES
    char sign;
    int x, y, direction, speed, color;
    int width, height;              //area, field size


//CONSTRUCTORS
    Ball();
    ~Ball();
    Ball(int d, int s, int yy, int xx, int c, int fH, int fW);  
    //s - start direction, v - speed, x,y- position, c-color

//GETTERS



//METHODS
    void setAreaSize(int, int);
    void moveBall(void);
};

他のファイルには、このクラスを使用する私のプログラムがあります:

.../*including some libs */...

.../*declaring some attributes */...

Ball *balls;
pthread_t *threads;
int howManyBalls;
int i;              //helper for loops

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;

struct timespec delay = {       //our speed or rather delay ;)
             1,
             0
    };

/* Function declarations */
void initBalls(void);
void initThreads(void);
void *threadBallFunction(void *arg);



//MAIN FUNCTION ----------------------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
    ... /*some code*/...

    initBalls();
    initThreads();

    ... /* some code */       

    return 0;
}

//FUNCTIONS IMPLEMENTATIONS ----------------------------------------------------------------------------------

/* INIT BALLS */
void initBalls(void){
    balls = new Ball[howManyBalls];     //creating our balls array with appropriate size

    int ballY, ballX, ballDirection, ballColor;

    srand(time(0));                 //resetting the random number generator

    for(i=0;i<howManyBalls;i++){
        ballY = (rand()%(frameWidth-1))-i;
        ballX = (rand()%(frameHeight-1))-i;
        ballDirection = rand()%8+1;
        ballColor = rand()%7+1;

        balls[i] = Ball(ballDirection,2,ballX,ballY,ballColor, frameHeight, frameWidth);        

    }
}

void *threadBallFunction(void *threadIndex) {
    do{
        /* WHAT HERE ?? */
    }
    while(1);
}

/* INIT THREADS */
void initThreads(void){
    threads = new pthread_t[howManyBalls];
    void *exit_status;
    int threadIdx;

    for (threadIdx = 0; threadIdx < howManyBalls; threadIdx++) {
        pthread_create(&threads[threadIdx], NULL, threadBallFunction, &threadIdx);
        pthread_join(threads[threadIdx], &exit_status);
    }
}

だから、今私はボールが独自のスレッドを持っていることを望んでいます。すべてのスレッドは、同じ関数 (threadBallFunction) にリンクされています。ここで、1 つのボールだけを移動します。どのボールですか? これは、threadBallFunction に渡される引数によって指定されます。ボールとスレッドは別々の配列に格納する必要があります。ボールの数はユーザー入力によって指定されます。ボールの移動は無限でなければなりません。

ここでミューテックスまたは条件変数を使用する方法がわかりません...助けを楽しみにしています、

//編集: より正確な質問:

無限ループで同じ関数にリンクされた多くのスレッドがあります。この関数で同期スレッドの条件変数メソッドを使用することは可能ですか??

//EDIT2 (Ahmed に感謝しますが...) OK、それは私にとって本当に役に立ちます。どうもありがとうございました ;) buuuut は、スレッドが無限に動作し、インクリメントされるたびに「カウンター」値を出力するようにします。各インクリメントまたは印刷間の時間は 1 秒にする必要があります。

例えば:

カウンター = 0;

Thread1-IncCounterBy(2)

Thread2- IncCounterBy(5)

私のプログラムは次のように出力するはずです:

2 (1秒後に+2)

7 (1秒後に+5)

9 (1秒後に+2)

14 (1秒後に+5)

16 (1秒後に+2)

21 (1秒後に+5)

... CTRL+C で停止するまで

これを管理する方法は?

敬具

4

2 に答える 2

0

あなたの特定の質問:「この関数で同期スレッドの条件変数メソッドを使用することは可能ですか」

あなたが本当に求めている動作についてはまだ不明なので、両方のケースを考えてみましょう:


ケース 1: スレッドを自律的に実行し、それぞれがスケジュールされた期間にカウンターを個別に更新する必要があります。

答えは、このアプリケーションでは、条件変数は正しい同期方法ではないということです。条件変数は、生産者と消費者の設計パターン向けです。特に:

* pthread_cond_broadcast() および pthread_cond_signal() 関数は、cond で現在ブロックされているスレッドがない場合は効果がありません。 http://linux.die.net/man/3/pthread_cond_signal *

あなたが求めているのは、共有状態オブジェクト (カウンター) での自律的な処理です。この場合、同時アクセスを防ぐために共有状態を単純にミューテックスで保護する必要があるという点で Ahmed は正しいです。

ケース 2: 各スレッドで、1 つのスレッドが実行され、1 秒間待機してから、パラメーターの量によってカウンターを更新する、ある種のラウンド ロビン処理を実行する必要があります。次に、次のスレッドが実行され、1 秒間待機して、異なるパラメーター量でカウンターを更新します。というように、最初のスレッドにループバックするまで続きます。

このより多くのケースは、カウンターのインクリメント フローの例と一致します。この場合、スレッドの数が 2 である限り、条件変数を使用することができ、それらを決定論的な方法で開始するようにしてください。2 つ以上のスレッドがある場合、それらの優先度が異なる場合を除き、実行順序の保証はありません。また、そのようなループでそれらを開始しても、どちらが最初に実行されるかは保証されません。

この場合、他のすべてのスレッドが待機している間、一度に 1 つのスレッドのみが動作します。これは、マルチスレッド ソリューションの良い候補ではありません。より良いパターンは、単一のスレッドと作業キューです。これにより、必要なさまざまなインクリメント量の循環キューを作成し、単一のスレッドをループで実行して 1 秒待機させ、プルがキューから次のインクリメント量を読み取り、カウンターをインクリメントし、キュー ポインターをインクリメントして、繰り返すことを意味します。 .

于 2013-01-16T15:39:18.007 に答える
0

ミューテックスは非常に理解しやすく、使用も簡単です。クラスがあるとしましょう

class A{
        static int counter;
    public:
        static void IncCounterBy(int increment){
            counter += increment;
        }
    };

すべてがこの関数にアクセスしている 100 のスレッドがあると仮定すると、いつでも 2 つ以上のスレッドが同じ関数に同時にアクセスする可能性があり、それぞれが元の値をコピーし、それをインクリメントします。

Thread1-IncCounterBy(2)

Thread2- IncCounterBy(5)

Thread3- IncCounterBy(1)

これは =>> A::counter = 3; で終わります。

Boost::Mutex の使い方

class A{
        static int counter;
        boost::mutex Guard;
    public:
        static void IncCounterBy(int increment){
        Guard.lock();
        counter += increment;
        Guard.unlock();
        //Or you can use "boost::mutex::scoped_lock  lock(Guard);" to guard a function
    };
于 2013-01-15T23:36:23.553 に答える