Java 为什么我的线程不同步?

Java 为什么我的线程不同步?,java,multithreading,synchronization,Java,Multithreading,Synchronization,我试图掌握同步线程,但我不理解我遇到的问题 有人能帮我诊断一下吗?或者,更好的是,解释一下我如何为自己诊断 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;

我试图掌握同步线程,但我不理解我遇到的问题

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

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();
    }
  }
}

相反,所有线程都会增加数组,并开始相互打印

结果没有什么出人意料的。创建n个线程。你告诉所有的线程开始。每个threads 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() {

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

或者:不要在ThreadableClass中创建
changeArray()
方法。。。创建一个类

ArrayUpdater {
  int arr[] to update

  synchronized changeArray() ...

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

结果没有什么出人意料的。创建n个线程。你告诉所有的线程开始。每个threads 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() {

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

或者:不要在ThreadableClass中创建
changeArray()
方法。。。创建一个类

ArrayUpdater {
  int arr[] to update

  synchronized changeArray() ...

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

因为您使用
新线程类(barrier,arr)
为每个theard提供
新的
实例,所以基本上,所有TheADR都使用不同的
线程类
对象
,所以您的代码同步方法并行运行,因此,您需要使用单个
ThreadableClass
对象,如下所示:

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

重要的一点是,同步是一次为单个线程提供对对象的访问(即密钥)。如果您为每个线程使用不同的对象,线程不会等待密钥,因为每个线程都有自己的密钥(如您的示例中所示)。

因为您使用
新的ThreadableClass(barrier,arr)
为每个线程提供
新的
实例,所有TheADR都使用不同的
ThreadableClass
对象,因此您的代码同步方法并行运行,因此您需要使用单个
ThreadableClass
对象,如下所示:

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

重要的一点是,同步是一次为单个线程提供对对象的访问(即密钥)。如果您对每个线程使用不同的对象,线程不会等待密钥,因为每个线程都有自己的密钥(如您的示例中所示)。

。非常感谢你。我现在明白了。通过阅读您的解决方案,我决定在Contoller类中创建ThreadableClass的单个实例,然后将每个线程传递给同一个实例。(只是想给下一个人提供一些额外的背景,让他思考同样的事情)。再次感谢鬼猫!你真的帮了大忙。既然你似乎知道你在这些地方做些什么,我应该在风格上做些什么改进吗?有什么我不应该遵守的习俗吗?(生日快乐!!!)就几个;因为我马上就要睡觉了;-)A) 即使使用静态主控灯;试着在那里做尽可能少的事情。比如:编写一个方法,该方法接受该数字“n”,并创建一个线程列表;还有另一种方法继续对它们起作用。您只需读取数字,然后调用这些方法。B) 尝试将字段设置为最终字段,以便编译器可以帮助您确保