【发布时间】:2021-08-30 22:01:54
【问题描述】:
我正在开发一个多线程的素数生成器。我对这个多线程进程的目标是每个进程将检查一个数字。我确实有一些工作代码,但我在“锁定”概念方面遇到了一些问题,其中计划运行 2 个进程彼此非常接近。
Claimed Lock: 0; Claimed Number: 75827; isPrime: false
Claimed Lock: 1; Claimed Number: 75829; isPrime: false
Claimed Lock: 2; Claimed Number: 75831; isPrime: false
Claimed Lock: 4; Claimed Number: 75835; isPrime: false
Claimed Lock: 5; Claimed Number: 75837; isPrime: false
Claimed Lock: 5; Claimed Number: 75837; isPrime: false
Claimed Lock: 3; Claimed Number: 75833; isPrime: true
Claimed Lock: 6; Claimed Number: 75839; isPrime: false.
(您可以看到 2 个锁 - 即 5 个被调用两次 - 它们应该是不同的)
我这个程序的主要目标是让 1 个线程计算基于 1 的素数。根据 Java JVM 向代码内部的 int cores 变量报告的内容,将有 n 个线程。
以下是我的程序的简要说明:
-
程序开始获取给定计算机的逻辑 cpu 核心数
-
创建一个包含 [2] [CPU 核心数] 的二维数组
-
Array[0][i] = 填充 2k+1(奇数)个潜在质数(这样做是因为 2 是唯一已知的偶数质数)
-
Array[1][i] = 填充“-1” = 表示该数字已准备好被进程/线程获取
-
然后程序启动 n 个线程(基于 cpu 核心数)
-
已经创建的新线程应该寻找下一个可用的 Array[1][i] == -1 并将其更改为值 2。(2 表示进程锁和/或数字是正在检查是否为素数)
-6a。 n 个子进程检查是否为素数,并将 Array[1][i] 更改为 1 或 0(1 表示它是素数或 0 表示它不是素数)
-6b。子进程终止
-
父进程 - Main 将忙于等待,直到所有 Array[1][i] 为 1 或 0
-
重复步骤 3
我在这个逻辑上遗漏了什么或做错了什么?我相信我在 JVM/OS 计划中遗漏了一些东西。但是,我觉得我在这个假设中也可能不正确?我可以做些什么来解决这个问题?
这是我的代码: 多线程类
class MultithreadCalculate extends Thread {
public void run() {
try {
int indexNum = -1;
for (int i = 0; i < MultiThreadPrimeNumGen.cores; i++) {
if (MultiThreadPrimeNumGen.primeArray[1][i] == -1) {
MultiThreadPrimeNumGen.primeArray[1][i] = 2;
indexNum = i;
break;
}
}
boolean isPrime = true;
for (int i = 2; i < MultiThreadPrimeNumGen.primeArray[0][indexNum]; i++) {
if (MultiThreadPrimeNumGen.primeArray[0][indexNum] % i == 0) {
isPrime = false;
MultiThreadPrimeNumGen.primeArray[1][indexNum] = 0;
break;
}
}
if (isPrime) {
MultiThreadPrimeNumGen.primeArray[1][indexNum] = 1;
}
System.out.println("Thread " + Thread.currentThread().getId() + "; Claimed Lock: " + indexNum + "; Claimed Number: " + MultiThreadPrimeNumGen.primeArray[0][indexNum] + "; isPrime: " + isPrime);
}
catch (Exception e) {
System.out.println("Exception is caught");
}
}
}
这里是主类:
public class MultiThreadPrimeNumGen {
public static int[][] primeArray;
public static int primeBase = 1;
public static int cores;
private static void fillArray() {
for (int i = 0; i < cores; i++) {
primeBase += 2;
primeArray[0][i] = primeBase;
}
for (int i = 0; i < cores; i++) {
primeArray[1][i] = -1;
}
}
public static void main(String[] args) throws FileNotFoundException {
File file = new File(System.getProperty("user.home") + "/Desktop" + "/PrimeNumber.txt");
PrintWriter out = new PrintWriter(file);
//Gets number of CPU Cores
cores = Runtime.getRuntime().availableProcessors();
System.out.println("Number of Cores: " + cores);
while (true) {
primeArray = new int[2][cores];
fillArray();
for (int i = 0; i < cores; i++) {
MultithreadCalculate multithreadCalculate = new MultithreadCalculate();
multithreadCalculate.start();
}
while (true) {
boolean flag = false;
for (int i = 0; i < cores; i++) {
if ((primeArray[1][i] == 0) || (primeArray[1][i] == 1)) {
flag = true;
} else {
flag = false;
break;
}
}
if (flag) {
break;
}
}
for (int i = 0; i < cores; i++) {
if (primeArray[1][i] == 1) {
out.println("PrimeNum: " + primeArray[0][i]);
out.flush();
}
}
}
}
}
【问题讨论】:
-
我根本看不到任何锁定。为什么两个线程不能同时看到相同的 -1?
-
我认为我目前对并发编程的了解有点少。我想我认为实现(上面列表中的第 6 步)被认为是一种锁定机制。什么是良好的基本理解的好资源?
-
您可以查看official tutorial 了解同步的基本介绍。 Java Concurrency in Practice 是一本适合深入学习的好书。
-
另外,我只想说非常感谢您提供的文档!
标签: java multithreading jvm primes cpu-usage