Java 即使使用synchronized关键字,线程输出也不一致

Java 即使使用synchronized关键字,线程输出也不一致,java,multithreading,synchronization,thread-safety,Java,Multithreading,Synchronization,Thread Safety,我对线程非常陌生。我写了一个代码,并期望我的输出为20000。但事实并非如此。请查找以下代码: class Runner4 implements Runnable { static int count = 0; public synchronized void increase() { count++; } @Override public void run() { for (int i = 0; i < 100

我对线程非常陌生。我写了一个代码,并期望我的输出为20000。但事实并非如此。请查找以下代码:

class Runner4 implements Runnable {

    static int count = 0;

    public synchronized void increase() {
        count++;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            increase();
        }
    }
}

public class threading4 {

    public static void main(String[] args) {

        Thread t1 = new Thread(new Runner4());
        t1.start();
        Thread t2 = new Thread(new Runner4());
        t2.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println(Runner4.count);
    }
}
类Runner4实现Runnable{
静态整数计数=0;
公共空间增加(){
计数++;
}
@凌驾
公开募捐{
对于(int i=0;i<10000;i++){
增加();
}
}
}
公共类线程4{
公共静态void main(字符串[]args){
线程t1=新线程(新Runner4());
t1.start();
线程t2=新线程(新Runner4());
t2.start();
试一试{
t1.join();
t2.连接();
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
System.out.println(Runner4.count);
}
}
有什么解释吗


谢谢

如果
计数
不是
静态的
,那么代码就可以工作

public synchronized void increase() {
    // method body
} 
相当于

public void increase() {
    synchronized(this) {
        // method body
    }
}

由于
count
static
,因此
t1
t2
都使用不同的锁访问它,从而导致非确定性行为。要么使
Runner4.increase
在公共锁上同步(
Runner4.class
私有静态
锁对象可以正常工作),要么使
计数
非静态。

您正在代码中的两个不同对象上同步(对应于您创建的两个对象)。因此,共享静态变量没有任何保护,您会得到不可预测的结果。基本上,程序中没有有效的同步。您可以通过简单的修改来修复此问题

更改:

public synchronized void increase(){
    count++;
}
致:


请注意,我并不是说这是实现此类同步的最佳方式,但重要的是,如果要修改类级变量,也需要类级同步。

您试图实现所需的方式实际上不是最佳方式。 更好的方法是定义一个名为Counter的类,如下所示:

public class Counter 
{
    int count;
    public Counter()
    {
        count = 0;
    }
    public synchronized void increase() {
        count++;
    }

    public int getCount()
    {
        return count;
    }

}
该类具有增加计数器并获取计数器的方法。 现在需要做的是让两个调用increase()方法的线程共享一个计数器对象。因此,您的线程类将如下所示:

class Runner4 extends Thread {

    Counter count;
    public Runner4(Counter c)
    {
        count = c;
    }


    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            count.increase();
        }

    }
}
class Runner4 extends Thread {

    Counter count;
    public Runner4(Counter c)
    {
        count = c;
    }


    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            count.increase();
        }

    }
}
public static void main(String[] args) {

        Counter count = new Counter();
        Thread t1 = new Runner4(count);
        t1.start();
        Thread t2 = new Runner4(count);
        t2.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println(count.getCount());
    }