0

我是 C++ 新手并尝试使用 Pthread 和 Ncurses 库。我正在制作程序,它在终端屏幕上显示飞球。我创建了一个 Ball 类:

在文件 Ball.h 声明中,在 Ball.c 实现中。球.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,我将只移动一个球,哪个球?它将由传递给 threadBallFunction 的参数指定。球和螺纹应存储在单独的数组中。球数由用户输入指定。移动的球应该是无穷无尽的。

我不知道如何在这里使用互斥锁或条件变量......期待任何帮助,

//编辑:更精确的问题:

我有许多线程通过无限循环链接到同一个函数。是否可以在此函数中使用同步线程的条件变量方法?

//EDIT2(谢谢Ahmed,但是...) 好的,这对我很有帮助。非常感谢;) 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:您希望线程自主运行,并且每个线程在其自己的预定周期内独立更新计数器:

答案是对于这个应用程序,条件变量不是正确的同步方法。条件变量确实适用于生产者消费者设计模式。尤其是:

*如果当前没有线程阻塞在 cond 上,pthread_cond_broadcast() 和 pthread_cond_signal() 函数将无效。 http://linux.die.net/man/3/pthread_cond_signal *

您要求的是对共享状态对象(您的计数器)的自主处理。在这种情况下,Ahmed 是正确的,因为共享状态应该简单地由互斥锁保护以防止同时访问。

情况 2:您希望每个线程执行某种循环处理,其中一个线程运行,等待 1 秒,然后按其参数量更新计数器。然后下一个线程运行,等待 1 秒并通过其不同的参数量更新计数器。依此类推,直到您循环回第一个线程。

这种更多情况与您的示例计数器增量流相匹配。在这种情况下,只要线程数为 2,就可以使用条件变量,并且确保以确定的方式启动它们。如果有超过 2 个线程,则除非它们具有不同的优先级,否则无法保证运行顺序。同样在这样的循环中启动它们并不能保证哪个将首先执行。

在这种情况下,一次只有一个线程在工作,而所有其他线程都在等待。这不是多线程解决方案的好选择。更好的模式是单线程和工作队列。我的意思是创建一个所需的各种增量的循环队列,让一个线程在循环中运行,它等待 1 秒,从队列中读取下一个增量并递增计数器,递增队列指针,然后重复.

于 2013-01-16T15:39:18.007 回答
0

互斥量也很容易理解和使用,假设你有一个类

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

假设有 100 个线程都在访问这个函数,在任何时候 2 个线程 - 或更多 - 可以同时访问同一个函数,每个线程将复制原始值然后递增它所以如果 A::counter = 3

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 回答