gpt4 book ai didi

c++ - 在 C++ ncurses 项目中使用互斥锁的正确方法?

转载 作者:太空狗 更新时间:2023-10-29 21:32:09 26 4
gpt4 key购买 nike

我找不到写一个好的条件来解决我的问题的方法。正如您在包含的图像中看到的那样,屏幕中间有一条线,球不断地上下移动并在一段时间后消失。新球也层出不穷。

my image

我的任务是使用互斥体,这样只有 N 个球(2 或 3)可以在线上方,其余的都在等待轮到他们。

我尝试了几个选项,这是最近的一个。这可能没有多大意义,但我暂时没有其他想法:

来自 ball.cpp 的片段:

Ball::Ball(int nr)
{
this->nr = nr;
changeDirection();
this->x = 40;
this->y = 24;
this->lastX = 0;
this->lastY = 0;
this->bounceCounter = 0;
this->isAboveTheLine = false;
}

........

if(y < 12) {
isAboveTheLine = true;
}
else if(y >= 12) {
isAboveTheLine = false;
}

从 main.cpp 开始:

std::mutex m;

void ballFunction(int a)
{
int counter = 2;
int nr = a;
while (run && shared->balls[nr]->bounceCounter < 5)
{
usleep(50000);

shared->balls[nr]->updateBall();

if(shared->balls[nr]->isAboveTheLine == true) {
counter++;
}
else if(shared->balls[nr]->isAboveTheLine == false) {
counter--;
}

if(counter >= 3) {
m.lock();
}
else if (counter<2) {
m.unlock();
}
}

shared->balls[nr]->x = -1;
shared->balls[nr]->y = -1;
}

编辑:我添加了 int main():

int main() {
srand(time(NULL));

window = new Window();

int i = 0;

std::vector<std::thread> threads;

std::thread threadWindow(updateWindow2);
std::thread threadExit(exit);

while(run) {
window->addBall();
threads.push_back(std::thread(ballFunction, i));
i++;
sleep(1);
}

threadWindow.join();
threadExit.join();

for(int j=2; j<i+2; j++) {
threads[j].join();
}

return 0;
}

它根本不起作用。我是在朝着正确的方向前进,还是需要采用不同的方法?

最佳答案

如果直接回答你的问题,我会用condition_variable为了那个原因。等待直到出现球的空闲位置(上部的球数变得少于球数限制)。当球离开限制球号区域时通知其他线程:

std::mutex m;
std::condition_variable cv;
int counter = 2;

void ballFunction(int a)
{
int nr = a;
while (shared->balls[nr]->bounceCounter < 5)
{
usleep(50000);

bool previousIsAbove = shared->balls[nr]->isAboveTheLine;
shared->balls[nr]->updateBall();
// check if state changed
if (previousIsAbove == shared->balls[nr]->isAboveTheLine) continue;

if(previousIsAbove) // ball went down the line
{
std::unique_lock<std::mutex> locker(m);
counter++;
cv.notify_one();
}
else
{
std::unique_lock<std::mutex> locker(m);
cv.wait(locker, [&](){return !run || counter > 0;});
if (!run) return;
counter--;
}
}

shared->balls[nr]->x = -1;
shared->balls[nr]->y = -1;
}

但代码有更多问题,我将解释最关键的问题。

首先,您的counterballFunction() 中的一个非静态局部变量。所有 ballFunction 调用者都有自己的 counter 版本,但您不想将它用作所有线程的一个共享变量。将它放在 ballFunction() 之外。您还使用 2 对其进行了初始化,因此我假设您希望将其用作该行上方的多个空闲位置。但是当球越过线时你增加它并检查它与'2'和'3'。反其道而行之 - 当球越过线时减少自由位置计数,并在减少并让球进一步上升之前检查是否大于 0

假设您修复了该问题,您仍然可以在没有任何关键部分处理和线程同步的情况下读取/写入 counter 值。这可能会导致数据竞争并且是未定义的行为(不是程序)。仅以线程安全的方式处理共享数据。例如,如果您使用 mutex 来同步线程(就像在这种情况下),则只能“在锁定的互斥量下”访问它以将同时使用共享数据的线程数限制为一个。如果您决定改用 atomic - 仅使用 CAS (compare & swap) atomic operation 执行检查 + 递增/递减 .

run 也是如此(您也可以从不同的线程访问它,至少使其成为 volatile)。注意:如果您使用我的代码。

对于每个进入上半部分的球,每次迭代都会增加球的数量。仅在越过线时执行此操作(我通过检查球在更新其位置之前和之后的位置来做到这一点,您也可以从之前的迭代中保存它以避免重复检查)。

我没有涉及可读性、样式等问题,只涉及主要的多线程和逻辑问题。

附言:

New balls are also appearing endlessly

因为你在这里无休止地生成它们:

while(run) {
window->addBall();
threads.push_back(std::thread(ballFunction, i));
i++;
sleep(1);
}

我不知道你想让你的程序做什么。

关于c++ - 在 C++ ncurses 项目中使用互斥锁的正确方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56042718/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com