Как сделать функцию, которая может выполняться только в одном потоке одновременно? - PullRequest
1 голос
/ 01 февраля 2020

У меня есть программа, которую я использую, чтобы найти простые числа. он выполняется в нескольких потоках. Я использую функцию GetNextNumber () для вызова потоков, чтобы получить число, чтобы проверить, является ли оно простым, однако кажется, что эта функция выполняется одновременно более чем одним потоком, поэтому иногда два потока получают один и тот же номер. вот мой код:

#include "pch.h"
#include <cmath>
#include <fstream>
#include <thread>
#include <iostream>
#include <string>

int nextInt = 1;
std::ofstream file;

bool TestPrime(int number)
{
    double rootInt = sqrt(number);
    for (int i = 3; i <= rootInt; i += 2)
    {
        double divValue = (double)number / i;
        if (int(divValue) == divValue)
        {
            return false;
        }
    }
    return true;
}
int GetNextNumber()
{
    return (nextInt += 2);
}

void PrimeFinderThread()
{
    while (true)
    {
        int number = GetNextNumber();
        bool isPrime = TestPrime(number);
        if (isPrime)
        {
            std::string fileOutput = std::to_string(number) + "-";
            file << fileOutput;
        }
    }
}

int main() {
    file.open("primes.txt", std::ofstream::app);
    file << 2 << "-";
    std::thread threads[4];
    for (int i = 0; i < 4; i++) {
        threads[i] = std::thread(PrimeFinderThread);
    }
    for (int i = 0; i < 4; i++) {
        threads[i].join();
    }
    return 0;
}

Ответы [ 2 ]

2 голосов
/ 01 февраля 2020

Использование мьютекса является допустимым решением, но в этом случае оно приводит к ненужным накладным расходам. Вы можете просто сделать nextId atomi c:

std::atomic<int> nextId{1};

Это сделает операцию приращения в GetNextNumber atomi c, поэтому никакие два потока не получат одинаковое значение.

1 голос
/ 01 февраля 2020

Используйте std :: mutex с std :: lock_guard . Это предотвратит одновременное выполнение функции.

#include "pch.h"
#include <cmath>
#include <fstream>
#include <thread>
#include <iostream>
#include <string>
#include <mutex>

int nextInt = 1;
std::ofstream file;

bool TestPrime(int number)
{
    double rootInt = sqrt(number);
    for (int i = 3; i <= rootInt; i += 2)
    {
        double divValue = (double)number / i;
        if (int(divValue) == divValue)
        {
            return false;
        }
    }
    return true;
}
int GetNextNumber()
{
    static std::mutex m;
    const std::lock_guard<std::mutex> lock(m);
    return (nextInt += 2);
}

void PrimeFinderThread()
{
    while (true)
    {
        int number = GetNextNumber();
        bool isPrime = TestPrime(number);
        if (isPrime)
        {
            std::string fileOutput = std::to_string(number) + "-";
            file << fileOutput;
        }
    }
}

int main() {
    file.open("primes.txt", std::ofstream::app);
    file << 2 << "-";
    std::thread threads[4];
    for (int i = 0; i < 4; i++) {
        threads[i] = std::thread(PrimeFinderThread);
    }
    for (int i = 0; i < 4; i++) {
        threads[i].join();
    }
    return 0;
}
...