Java 基本多线程问题

Java 基本多线程问题,java,multithreading,Java,Multithreading,如果我将增量函数声明为非静态函数,那么最后计数器的值将不会是200万 另一方面,当增量方法定义为静态时,它可以正常工作 据我所知,所有进程对象只有一个增量函数。。那么为什么我必须将它声明为静态方法呢 谢谢声明它为静态将导致synchronized锁定Process.class实例。因此,所有正在运行的线程都将阻塞增量方法中的对象。删除static将导致每个线程只阻塞线程实例,在您的情况下,线程实例有两个 因此,计数器变量将并行递增,并且正如多次指出的那样,int递增不是线程安全的 据我所知,所有

如果我将增量函数声明为非静态函数,那么最后计数器的值将不会是200万

另一方面,当增量方法定义为静态时,它可以正常工作

据我所知,所有进程对象只有一个增量函数。。那么为什么我必须将它声明为静态方法呢


谢谢

声明它为静态将导致synchronized锁定Process.class实例。因此,所有正在运行的线程都将阻塞增量方法中的对象。删除static将导致每个线程只阻塞线程实例,在您的情况下,线程实例有两个

因此,计数器变量将并行递增,并且正如多次指出的那样,int递增不是线程安全的

据我所知,所有进程对象只有一个增量函数

Process类有一个增量函数,但同步是在对象上完成的,而不是在方法上完成的,例如:

package demo5;

class Process extends Thread {

static int counter = 0;

public static  synchronized void increment() { counter++; }

public void run() {
    for (int i = 0; i < 1000000; i++)
    {
        increment();
    }
    System.out.println("Done.");
  }
}

public class App {

public static void main(String[] args) throws InterruptedException {
    Process p1 = new Process();
    Process p2 = new Process();
    p1.start();
    p2.start();

    p1.join();
    p2.join();

    System.out.println("Value of count is :" + p1.counter);

}

}
相当于:

class Process{
     public synchronized void increment() { counter++; }
}
编辑:回答鲁基的问题

class Process{
     public void increment() { 
           synchronized(this){
                  counter++; 
            }
}
相当于

class Process{
     public static synchronized void increment() { counter++; }
}

将其声明为静态将导致同步进程锁定在Process.class实例上。因此,所有正在运行的线程都将阻塞增量方法中的对象。删除static将导致每个线程只阻塞线程实例,在您的情况下,线程实例有两个

因此,计数器变量将并行递增,并且正如多次指出的那样,int递增不是线程安全的

据我所知,所有进程对象只有一个增量函数

Process类有一个增量函数,但同步是在对象上完成的,而不是在方法上完成的,例如:

package demo5;

class Process extends Thread {

static int counter = 0;

public static  synchronized void increment() { counter++; }

public void run() {
    for (int i = 0; i < 1000000; i++)
    {
        increment();
    }
    System.out.println("Done.");
  }
}

public class App {

public static void main(String[] args) throws InterruptedException {
    Process p1 = new Process();
    Process p2 = new Process();
    p1.start();
    p2.start();

    p1.join();
    p2.join();

    System.out.println("Value of count is :" + p1.counter);

}

}
相当于:

class Process{
     public synchronized void increment() { counter++; }
}
编辑:回答鲁基的问题

class Process{
     public void increment() { 
           synchronized(this){
                  counter++; 
            }
}
相当于

class Process{
     public static synchronized void increment() { counter++; }
}


您可能希望将int计数器替换为计数器-通过这种方式,您可以从方法中删除synchronized关键字,并且不管该方法是静态方法还是实例方法。

您可能希望将int计数器替换为计数器-通过这种方式,您可以从方法中删除synchronized关键字,不管该方法是静态方法还是实例方法。

你确定你的计数器是静态的吗?你甚至可以添加transient关键字来counter和delete synchronized,这样就可以了。@shevchik transient不会影响它。你是说易变的吗?即使那样也不行。约翰,你说得对,反复无常。为什么不起作用?因为增量是三个操作。读增量写。Volatile有助于单个操作的可见性,但由于增量是一个复合项,它对此无能为力。您确定您的计数器是静态的吗?您甚至可以添加transient关键字到counter并删除synchronized,这样就可以了。@shevchik transient不会影响它。你是说易变的吗?即使那样也不行。约翰,你说得对,反复无常。为什么不起作用?因为增量是三个操作。读增量写。Volatile有助于单个操作的可视性,但由于increment是一个复合函数,它对此无能为力。Ehm,你想告诉我编译器为创建的每个对象创建所有类成员函数吗。。?java有点新,是用cpp开发的before@Rouki对不起,让我说得更清楚一点。。我想我开始明白了。因此,当我将此方法声明为静态时,意味着它现在没有此功能。同步后的方法现在会是什么样子?@Rouki updated。因为总是有一个Process.class实例,锁会阻止任何数量的试图递增的实例。Ehm,你想告诉我编译器为每个创建的对象创建所有的类成员函数吗。。?java有点新,是用cpp开发的before@Rouki对不起,让我说得更清楚一点。。我想我开始明白了。因此,当我将此方法声明为静态时,意味着它现在没有此功能。同步后的方法现在会是什么样子?@Rouki updated。因此,由于始终存在一个Process.class实例,锁将阻止任何数量的试图递增的实例。