Java 关于线程和线程安全的混淆
为了更好地理解线程的概念,我们应该使用一个数字对象,通过它的方法可以增加、减少、平方和根。它的唯一属性是一个双倍数(初始化为number=1) 因此,如果我实例化Number对象并对该Number对象调用increment()、decrement()、square()和root()100000000次,则Number属性再次为1(如预期的那样) 现在的问题是我们应该实例化两个线程对象,一个调用增加/减少100000000次,另一个调用平方/根100000000次。 根据我们的老师的说法,结果是不一致的,即得到的结果是0而不是1,但在我的程序中,根据我是否在Thread类中使用synchronized(),它只会给我无穷大或1Java 关于线程和线程安全的混淆,java,multithreading,synchronized,Java,Multithreading,Synchronized,为了更好地理解线程的概念,我们应该使用一个数字对象,通过它的方法可以增加、减少、平方和根。它的唯一属性是一个双倍数(初始化为number=1) 因此,如果我实例化Number对象并对该Number对象调用increment()、decrement()、square()和root()100000000次,则Number属性再次为1(如预期的那样) 现在的问题是我们应该实例化两个线程对象,一个调用增加/减少100000000次,另一个调用平方/根100000000次。 根据我们的老师的说法,结果是不
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;
}
}