如何使这段代码中的线程独立运行
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
我是线程概念的新手,我试图更好地理解它们。阅读有关理论后,我决定用线程编写一个简单的程序。我在互联网上找到了这个(可能很简单)任务:
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