Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 线程和互斥_C++_Multithreading_Mutex_Locks - Fatal编程技术网

C++ 线程和互斥

C++ 线程和互斥,c++,multithreading,mutex,locks,C++,Multithreading,Mutex,Locks,我正在做一个模拟加油站的程序。车站里的每辆车都有自己的线索。每辆车必须循环通过一个位掩码,以检查泵是否打开,如果打开,则更新位掩码,加注,并通知其他车泵现在已打开。我当前的代码可以工作,但负载平衡存在一些问题。理想情况下,所有泵的使用量相同,所有汽车的加油量相等 编辑:我的程序基本上需要一些汽车、水泵和一段时间来运行测试。在此期间,汽车将通过不断调用此函数来检查泵是否打开 int Station::fillUp() { // loop through the pumps using the b

我正在做一个模拟加油站的程序。车站里的每辆车都有自己的线索。每辆车必须循环通过一个位掩码,以检查泵是否打开,如果打开,则更新位掩码,加注,并通知其他车泵现在已打开。我当前的代码可以工作,但负载平衡存在一些问题。理想情况下,所有泵的使用量相同,所有汽车的加油量相等

编辑:我的程序基本上需要一些汽车、水泵和一段时间来运行测试。在此期间,汽车将通过不断调用此函数来检查泵是否打开

int Station::fillUp()
{

// loop through the pumps using the bitmask to check if they are available
for (int i = 0; i < pumpsInStation; i++)
{

    //Check bitmask to see if pump is open
    stationMutex->lock();
    if ((freeMask & (1 << i)) == 0 )
    {

        //Turning the bit on
        freeMask |= (1 << i);
        stationMutex->unlock();

        // Sleeps thread for 30ms and increments counts
        pumps[i].fillTankUp();

        // Turning the bit back off
        stationMutex->lock();
        freeMask &= ~(1 << i);
        stationCondition->notify_one();
        stationMutex->unlock();

        // Sleep long enough for all cars to have a chance to fill up first.
        this_thread::sleep_for(std::chrono::milliseconds((((carsInStation-1) * 30) / pumpsInStation)-30));


        return 1;
    }
    stationMutex->unlock();
}

// If not pumps are available, wait until one becomes available.
stationCondition->wait(std::unique_lock<std::mutex>(*stationMutex));

return -1;
}
int Station::fillUp()
{
//使用位掩码循环检查泵是否可用
对于(int i=0;ilock();
如果((自由掩码和(1锁)();
freeMask&=~(1 notify_one();
stationMutex->unlock();
//睡足够长的时间,让所有的车都有机会先加满油。
此线程::睡眠(std::chrono::毫秒(((carsInStation-1)*30)/泵安装-30));
返回1;
}
stationMutex->unlock();
}
//如果泵不可用,则等待一台可用。
stationCondition->wait(std::unique_lock(*stationMutex));
返回-1;
}

我觉得这个问题与读取时锁定位掩码有关。是否需要在if检查周围设置某种互斥或锁定?

看起来每辆车都会首先检查泵0的可用性,如果泵忙,则会检查泵1,依此类推。鉴于此,我似乎期望泵0能够服务于most车型,其次是第二大车型的泵#1,一直到泵#(泵安装-1),只有在新车进站时所有泵同时使用的(相对罕见)情况下才会使用


如果您想获得更好的负载平衡,您可能应该让每辆车选择不同的随机顺序来迭代泵,而不是让它们都以相同的顺序检查泵的可用性。

看起来每辆车都会先检查泵0的可用性,如果泵忙,则会检查泵1,依此类推n、 考虑到这一点,我似乎认为泵#0将服务于最多的汽车,其次是泵#1服务于第二多的汽车,一直到泵#(泵安装-1),它只有在(相对罕见的)情况下才能使用,即新车进站时所有泵都同时使用


如果您想获得更好的负载平衡,您可能应该让每辆车选择不同的随机顺序来迭代泵,而不是让它们都以相同的顺序检查泵的可用性。

看起来每辆车都会先检查泵0的可用性,如果泵忙,则会检查泵1,依此类推n、 考虑到这一点,我似乎认为泵#0将服务于最多的汽车,其次是泵#1服务于第二多的汽车,一直到泵#(泵安装-1),它只有在(相对罕见的)情况下才能使用,即新车进站时所有泵都同时使用


如果您想获得更好的负载平衡,您可能应该让每辆车选择不同的随机顺序来迭代泵,而不是让它们都以相同的顺序检查泵的可用性。

看起来每辆车都会先检查泵0的可用性,如果泵忙,则会检查泵1,依此类推n、 考虑到这一点,我似乎认为泵#0将服务于最多的汽车,其次是泵#1服务于第二多的汽车,一直到泵#(泵安装-1),它只有在(相对罕见的)情况下才能使用,即新车进站时所有泵都同时使用


如果您想获得更好的负载平衡,您可能应该让每辆车选择不同的随机顺序来迭代泵,而不是让它们都以相同的顺序检查泵的可用性。

假设互斥锁有一个与之关联的队列,其中包含等待的线程。现在,您的一个线程成功地获取保护被占用站点位掩码的互斥锁,检查某个特定位置是否空闲。如果不是,它将再次释放互斥锁并循环,结果返回到等待互斥锁的线程队列的末尾。首先,这是不公平的,因为等待的第一个线程不能保证获得下一个空闲插槽,只有在该插槽发生时ns是其循环计数器上的一个。其次,它会导致大量的上下文切换,这对性能不利。请注意,您的方法仍应产生正确的结果,即在访问单个加油站时没有两辆车发生碰撞,但其行为是次优的

你应该做的是:

  • 锁定互斥锁,以独占方式访问可能的加油站
  • 找到下一个免费加油站
  • 如果没有可用的工作站,等待条件变量并在点2重新启动
  • 将插槽标记为已占用并释放互斥锁
  • 给车加满油(这是模拟中的睡眠实际有意义的地方,另一个没有)
  • 锁定互斥锁
  • 将插槽标记为空闲,并向条件变量发送信号以唤醒其他插槽
  • 再次释放互斥锁

  • 为了防止您不清楚这一部分,等待条件变量会在等待时隐式释放互斥体,然后重新获取它!

    假设互斥体有一个与之关联的队列,其中包含等待的线程。现在,您的一个线程设法获取保护已占用站点位掩码的互斥体,检查如果一个特定的位置是空闲的,如果它不是空闲的,它将再次释放互斥锁并循环,只返回到thr队列的末尾
    int Station::acquirePump()
    {
        // loop through the pumps using the bitmask to check if they are available
        ScopedLocker locker(&stationMutex);
        for (int i = 0; i < pumpsInStation; i++)
        {
            // Check bitmask to see if pump is open
            if ((freeMask & (1 << i)) == 0 )
            {
                //Turning the bit on
                freeMask |= (1 << i);
                return i;
            }
        }
        return -1;
    }
    
    void Station::releasePump(int n)
    {
        ScopedLocker locker(&stationMutex);
        freeMask &= ~(1 << n);
        stationCondition->notify_one();
    }
    
    bool Station::fillUp()
    {
        // If a pump is available:
        int i = acquirePump();
        if (i != -1)
        {
            // Sleeps thread for 30ms and increments counts
            pumps[i].fillTankUp();
            releasePump(i)
    
            // Sleep long enough for all cars to have a chance to fill up first.
            this_thread::sleep_for(std::chrono::milliseconds((((carsInStation-1) * 30) / pumpsInStation)-30));
            return true;
        }
        // If no pumps are available, wait until one becomes available.
        stationCondition->wait(std::unique_lock<std::mutex>(*stationMutex));
        return false;
    }
    
    int Station::acquirePump()
    {
        // loop through the pumps using the bitmask to check if they are available
        ScopedLocker locker(&stationMutex);
        for (int n = 0, i = startIndex; n < pumpsInStation; ++n, i = (i+1) % pumpsInStation)
        {
            // Check bitmask to see if pump is open
            if ((freeMask & (1 << i)) == 0 )
            {
                // Change the starting index used to search for a free pump for
                // the next car.
                startIndex = (startIndex+1) % pumpsInStation;
    
                // Turning the bit on
                freeMask |= (1 << i);
                return i;
            }
        }
        return -1;
    }