我正在学习 1Z0-851 Oracla Java SE 1.6 认证,我看到了这个问题:
任何人都可以向我解释这个答案吗?
并说当我这样想时我是否正确:如果doThings()
是静态的,尽管当一个方法不是static
一次时,每个TestSeven
对象都会同时访问 doThings 并不一致地修改 x 值,但时间只能进行一次访问。
我这样想对吗?
谢谢。
我正在学习 1Z0-851 Oracla Java SE 1.6 认证,我看到了这个问题:
任何人都可以向我解释这个答案吗?
并说当我这样想时我是否正确:如果doThings()
是静态的,尽管当一个方法不是static
一次时,每个TestSeven
对象都会同时访问 doThings 并不一致地修改 x 值,但时间只能进行一次访问。
我这样想对吗?
谢谢。
对,就是那样。目前,如果您创建两个实例TestSeven
并从 2 个不同的线程调用它们的doThings
方法,则无法保证x
会增加两次。例如下面的执行是合法的(T1和T2是两个线程):
T1: current = x //0
T2: current = x //0
T1: current++; // 1
T2: current++; // 1
T1: x = current; // 1
T2: x = current; // 1
因此,您已经调用了该方法两次,但 x 只增加了一次。
如果您将方法设为静态,那么即使您创建了许多实例,在给定时刻也只有一个线程能够执行它。
它不是线程安全的,因为x范围是“静态的”,即所有类实例都可以访问它,而doThings方法则不是。所以它只在类实例上同步。
因此,尽管使用了 synchronized 关键字,但可以有两个类实例同时访问x。
将方法设为静态将确保它一次只被调用一次。
该doThings()
方法是一个实例方法,正在读取和写入一个静态变量x
。通过doThings()
设为静态,它将在所有实例之间同步(类上的内在锁,而不是实例上的)。换句话说,就目前而言,该方法可以由多个线程同时调用,而将其设为静态会阻止这种情况。
如果 x 未标记为静态,那么该类是否是线程安全的?