Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 关于线程和线程安全的混淆_Java_Multithreading_Synchronized - Fatal编程技术网

Java 关于线程和线程安全的混淆

Java 关于线程和线程安全的混淆,java,multithreading,synchronized,Java,Multithreading,Synchronized,为了更好地理解线程的概念,我们应该使用一个数字对象,通过它的方法可以增加、减少、平方和根。它的唯一属性是一个双倍数(初始化为number=1) 因此,如果我实例化Number对象并对该Number对象调用increment()、decrement()、square()和root()100000000次,则Number属性再次为1(如预期的那样) 现在的问题是我们应该实例化两个线程对象,一个调用增加/减少100000000次,另一个调用平方/根100000000次。 根据我们的老师的说法,结果是不

为了更好地理解线程的概念,我们应该使用一个数字对象,通过它的方法可以增加、减少、平方和根。它的唯一属性是一个双倍数(初始化为number=1)

因此,如果我实例化Number对象并对该Number对象调用increment()、decrement()、square()和root()100000000次,则Number属性再次为1(如预期的那样)

现在的问题是我们应该实例化两个线程对象,一个调用增加/减少100000000次,另一个调用平方/根100000000次。 根据我们的老师的说法,结果是不一致的,即得到的结果是0而不是1,但在我的程序中,根据我是否在Thread类中使用synchronized(),它只会给我无穷大或1

public class Calculation {

    public static void main(String[] args) throws InterruptedException {
        Number num = new Number();
        Number num1 = new Number();

        for (int i = 0; i < 100000000; i++) {
            num.increment();
        }

        for (int i = 0; i < 100000000; i++) {
            num.decrement();
        }

        for (int i = 0; i < 100000000; i++) {
            num.square();
        }

        for (int i = 0; i < 100000000; i++) {
            num.root();
        }
        System.out.println(num.getNumber());
        CalcThread t1 = new CalcThread(num1, true);
        CalcThread t2 = new CalcThread(num1, false);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(num1.getNumber());   
    }
}
如果不使用synchronized,则得到无穷大是有意义的,因为它在同时对数字进行平方运算的同时也在增加,因此该数字很快就会过大,无法适应双字体大小,对吗? 我怎样才能理解老师所说的前后矛盾呢


提前感谢您的帮助。

a,似乎是这样。为了使事情变得真正不可预测,你可以添加布尔值,一方面随机决定是平方还是根,另一方面决定是递增还是递减。那么它看起来真的不可预测你已经看到了不一致性。当对变量进行更改的代码位于同步块/方法内时,一切正常。但是,当您删除该“线程安全”机制时,您会发现结果与您之前观察到的不同。如果删除同步的,您将看到您想要的不一致。如果没有,请在方法中的每个循环之间插入一个随机的小sleep(),并运行更多线程。>我如何获得老师所说的不一致性?<如果多线程程序遵循所有“同步”规则,则保证它以某种方式运行。但如果它违反了规则,就不能保证它会以任何特定的方式行事。测试多线程程序的正确性通常是徒劳的,因为违反规则的程序可能在某一天仍能正常工作,但在另一天却不能。它可以在一个操作系统上正常工作,但不能在另一个操作系统上正常工作。当系统负载较轻时,它可能正常工作,但在负载较重时,它可能无法正常工作,等等。这不是重点,我理解它应该是不一致的,但如果我删除代码中的synchronized()部分,我会一直得到无穷大的结果,这是不一致的。
public class CalcThread extends Thread {
    public Number num;
    public boolean decision;

    public CalcThread(Number num, boolean decision) {
        this.num = num;
        this.decision = decision;
    }

    @Override
    public void run() {
        synchronized(num) {
        if (this.decision) {
            for (int i = 0; i < 100000000; i++) {
                num.square();
            }
            for (int i = 0; i < 100000000; i++) {
                num.root();
            }
        } else {
            for (int i = 0; i < 100000000; i++) {
                num.increment();
            }
            for (int i = 0; i < 100000000; i++) {
                num.decrement();
            }
        }
        }
    }
}

public class Number {
    double number;
    public Number() {
        this.number = 1;    
    }

    public void increment() {
        this.number++;
    }

    public void decrement() {
        this.number--;
    }

    public void square() {
        this.number = this.number * this.number;
    }

    public void root() {
        this.number = Math.sqrt(this.number);
    }

    public double getNumber() {
        return number;
    }

    public void setNumber(double number) {
        this.number = number;
    }
}