如何使这段代码中的线程独立运行

How to make the threads in this code to go independently

我是线程概念的新手,我试图更好地理解它们。阅读有关理论后,我决定用线程编写一个简单的程序。我在互联网上找到了这个(可能很简单)任务:

Write a program that calculates prime numbers and numbers of Fibunacci on different threads.

a. The first thread starts searching for prime number from 1, until killing of the program and when a prime number is found the program must present the time for finding this number.

b. The second thread is calculating and printing numbers of Fibunacci from 1 until killing of the program. When a new number of Fibunacci is found the program prints this number and the time for calculating this number.

c. The time is shown in ms (milliseconds)

d. Think about strategies for not having overlapping messages from the console.

e. The program must work with large as possible numbers. When the number is too large to be held in type like unsigned long long the program stops the calculation of that kind of numbers and shows error message.

Example output:

Prime 1, 0.1 ms.

Fibunacci 1, 0.1 ms.

Prime 2, 0.1 ms.

Fibunacci 2, 0.1 ms.

Prime 3, 0.1 ms.

Fibunacci 3, 0.1 ms.

Fibunacci 5, 0.1 ms.

Prime 5, 0.1 ms.

Fibunacci 8, 0.1 ms.

Prime 7, 0.1 ms.

Fibunacci 13, 0.2 ms.

Fibbunaci 21, 0.1 ms.

Prime 11, 0.2 ms.

这是我写的代码:

#include <iostream> // std::cout
#include <string>   // std::cout << std::string
#include <thread>   // std::thread
#include <time.h>   // clock()
#include <mutex> // std::mutex

std::mutex mtx;
int timePrim, timeFib;

bool isPrime(int testedNumber) 
{
    if (testedNumber <= 2) return true;
    if (testedNumber % 2 == 0) return false;
    for (int i = 3; (i*i) <= testedNumber; i += 2) 
    {
        if (testedNumber % i == 0) return false;
    }
    return true;
}

// the function is realized by a recursive algorithm; credits to Whosebug ;)
bool isFibonacci(unsigned long long testedNumber, int a = 1, int b = 1)
{
    if (testedNumber == 0 || testedNumber == 1)
        return true;//returning true for 0 and 1 right away.
    int nextFib = a + b;//getting the next number in the sequence
    if (nextFib > testedNumber)
        return false;//if we have passed the tested number, it's not in the sequence
    else if (nextFib == testedNumber)
        return true;//if we have a perfect match, the tested number is in the sequence
    else
        isFibonacci(testedNumber, b, nextFib);//otherwise, get the next fibonacci number and repeat.
}

void CheckNumber(unsigned long long numberToCheck, bool ifPrime)
{
    bool result = false;
    if (ifPrime == true) 
    {
        result = isPrime(numberToCheck);
    }
    else
    {
        result = isFibonacci(numberToCheck);
    }
    if (result == true)
    {
        float currentTime = 0;
        std::string typeNumber = "";
        if (ifPrime == true)
        {
            typeNumber = "Prime";
            currentTime = (float)(clock() - timePrim) / CLOCKS_PER_SEC;
            timePrim = clock();
        }
        else
        {
            typeNumber = "Fibonacci";
            currentTime = (float)(clock() - timeFib) / CLOCKS_PER_SEC;
            timeFib = clock();
        }
        mtx.lock();
        std::cout << typeNumber << " number " << numberToCheck << "; time " << currentTime << std::endl;
        mtx.unlock();
    }
}

int main()
{
    timePrim = timeFib = clock();

    for (unsigned long long i = 0; true; i++) // endless for loop == while(true) // by requirements
    {
        std::thread primeThread = std::thread(CheckNumber, i, true);
        std::thread fibThread = std::thread(CheckNumber, i, false);
        primeThread.join();
        fibThread.join();
    }

}

据我了解,这两个线程应该相互独立,并尽可能快地打印结果相关函数找到一个数字。但是结果看起来很简单——按照主函数中 for 循环中迭代器前进的顺序而不是计算时间。 这是来自控制台的片段:

Prime number 0; time 0.005

Fibonacci number 0; time 0.007

Prime number 1; time 0.03

Fibonacci number 1; time 0.029

Prime number 2; time 0.093

Fibonacci number 2; time 0.092

Prime number 3; time 0.023

Fibonacci number 3; time 0.023

Prime number 5; time 0.05

Fibonacci number 5; time 0.052

Prime number 7; time 0.023

Fibonacci number 8; time 0.045

Prime number 11; time 0.038

Prime number 13; time 0.077

Fibonacci number 13; time 0.091

Prime number 17; time 0.019

Prime number 19; time 0.179

Fibonacci number 21; time 0.208

Prime number 23; time 0.027

为了创建独立的线程,我应该在这段代码中更正什么?运行?其中 is/are 我的 mistake/s?

// 抱歉,如果上面的英文文本不好 - 这不是我的母语,所以我可能犯了一些错误...

创建两个包含 std::thread 个对象的向量。一种用于斐波那契计算,一种用于素数计算。然后有两个循环:一个创建两个线程并将它们添加到向量中,然后另一个循环将向量中的所有线程连接起来。

当第二个循环等待第一个线程退出时,第一个循环中创建的所有线程将运行并行。


你现在正在做的是创建两个线程,然后立即等待它们结束,然后再次循环迭代。这意味着一次只有一个斐波那契数列和一个素数线程 运行。

现在您的程序为每个数字 i 创建线程,因此如果您计算素数和斐波那契数,其中 i 从 0 到 gazilion,它将创建和销毁 2 gazilions 个线程。创建线程需要进行系统调用,在循环中这样做并不是特别快。

您还让两个线程在提交更多工作之前相互等待。

这是你的程序在伪代码中的样子(与真实编程语言的任何相似之处纯属巧合):

def prime(i):
    calculate one prime

def fibo(i):
    calculate one fibo

for i from 0 to gazilion:
    prime_thread = create_and_run_thread(prime, i)  # expensive, runs gazilion times
    fibo_thread = create_and_run_thread(fibo, i)    # expensive, runs gazilion times

    wait_for(prime_thread)     # wait until single number is crunched
    wait_for(fibo_thread)      # wait until single number is crunched

    destroy_thread(prime_thread)                 
    destroy_thread(fibo_thread)                  

相反,您可以为每个任务创建 2 个永久线程并分别循环:

def prime():
    for i from 0 to gazilion:
        calculate one prime

def fibo():
    for i from 0 to gazilion:
        calculate one fibo


prime_thread = create_and_run_thread(prime)  # expensive, but runs only once
fibo_thread = create_and_run_thread(fibo)    # expensive, but runs only once

wait_for(prime_thread)     # you only wait until gazilion is reached
wait_for(fibo_thread)      # you only wait until gazilion is reached

destroy_thread(prime_thread)                 # runs oly once
destroy_thread(fibo_thread)                  # runs oly once