gpt4 book ai didi

java - 为什么我的线程不同步?

转载 作者:行者123 更新时间:2023-11-29 08:37:05 25 4
gpt4 key购买 nike

我正试图掌握同步线程,但我不明白我遇到的问题。

谁能帮我诊断一下,或者更好的是,解释一下我如何自己诊断一下?

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CyclicBarrier;

public class Controller {

public static void main(String[] args) {
int numThreads = 0;
List<Thread> threads = new ArrayList<>();

if (args.length > 0) {
numThreads = Integer.parseInt(args[0]);
}
else {
System.out.println("No arguments");
System.exit(1);
}

CyclicBarrier barrier = new CyclicBarrier(numThreads);
int arr[][] = new int[10][10];

for (int i = 0; i < numThreads; i++) {
Thread newThread = new Thread(new ThreadableClass(barrier, arr));
threads.add(newThread);
}

for (Thread thread : threads) {
thread.start();
}
}
}

有一个主要方法(上面)接受我想要的线程数作为命令行参数。并且有一个工作流程(如下),我的目标是增加二维数组中的所有元素并在下一个线程有机会执行相同操作之前打印数组:

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class ThreadableClass implements Runnable {

private CyclicBarrier barrier;
private int arr[][];

public ThreadableClass(CyclicBarrier barrier, int[][] arr) {
this.barrier = barrier;
this.arr = arr;
}

@Override
public void run() {
long threadId = Thread.currentThread().getId();
System.out.println(threadId + " Starting");

for (int i = 0; i < 10; i++) {
changeArray();
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}

private synchronized void changeArray() {
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length; j++) {
arr[i][j]++;
}
}
printArray();
}

private synchronized void printArray() {
System.out.println(Thread.currentThread().getId() + " is printing: ");
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
}

假设数组的大小为 2x2,预期的输出将如下所示:

1 1
1 1
2 2
2 2
3 3
3 3
4 4
4 4
...
...
(10 * numThreads)-1 (10 * numThreads)-1
(10 * numThreads)-1 (10 * numThreads)-1
(10 * numThreads) (10 * numThreads)
(10 * numThreads) (10 * numThreads)

相反,所有线程递增数组,并开始相互打印。

最佳答案

结果没什么令人惊讶。您创建了 n 个线程。你告诉所有线程开始。每个线程 run() 开始于:

long threadId = Thread.currentThread().getId();
System.out.println(threadId + " Starting");
...changeArray();

要更改共享数组。 写入数组后,您尝试同步(在那个障碍上)。那就太晚了!

要点是:您有 10 个不同的 ThreadableClass 实例。每一个都自己运作! synchronized 关键字……在这里根本不提供任何保护!

因为:synchronized 防止两个不同的线程在同一个对象上调用同一个方法。但是当你有多个对象,并且你的线程在那些不同的对象上调用该方法时,就没有没有锁定!您的代码的作用归结为:

threadA to call changeArray() .. on itself
threadB to call changeArray() .. on itself
threadC to call changeArray() .. on itself

...

换句话说:您授予 n 个线程访问该共享数组的权限。但是随后您允许那些 n 个线程同时进入 changeArray()。

一个简单的修复;改变

private synchronized void changeArray() {

private void changeArray() {
synchronized(arr) {

换句话说:确保n个线程必须锁定同一个监视器上;在这种情况下是共享数组。

或者:不是让 changeArray() 成为 ThreadableClass 中的一个方法...创建一个类

ArrayUpdater {
int arr[] to update

synchronized changeArray() ...

然后创建该类的一个实例;并为每个线程提供相同的实例。现在 sync'ed 方法将阻止多个线程进入!

关于java - 为什么我的线程不同步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43239368/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com