thinking in java 4th editon page 682 in chinese vision or 1163 in en vision
看得我很困惑 寻大虾帮助 谢谢 谢谢
import java.util.concurrent.*;public class AtomicityTest implements Runnable {
private int i = 100;
public int getValue() { return i; }
private synchronized void evenIncrement() { i++; i++; }
public void run() {
while(true)
evenIncrement();
}
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
AtomicityTest at = new AtomicityTest();
exec.execute(at);
//①try{Thread.sleep(1);}catch (InterruptedException ex){}
while(true) {
int val = at.getValue();
//②try{Thread.sleep(1);}catch (InterruptedException ex){}
if(val % 2 != 0) {
System.out.println(val);
System.exit(0);
}
}
}
} /* Output: (Sample)
191583767
*///:~
上面的代码(①②中的注释是我自己添的) 书上面说不能达到线程同步的效果 因为getValue()没有被synchronized 输出的不应该是101 而应该是191583767或者其他一个很奇怪的数但事实上 我去执行一下上面的代码 输出的确实101 也就是说书上错了吗?然后我分别在①②中加入sleep,按照我的想法, exec.execute(at)执行好之后遇到sleep 然后本来应该挂起的run()开始执行,即 错误产生 输出应该是非101 请问我的解释对吗? 然后书上错了吗?
谢谢
看得我很困惑 寻大虾帮助 谢谢 谢谢
import java.util.concurrent.*;public class AtomicityTest implements Runnable {
private int i = 100;
public int getValue() { return i; }
private synchronized void evenIncrement() { i++; i++; }
public void run() {
while(true)
evenIncrement();
}
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
AtomicityTest at = new AtomicityTest();
exec.execute(at);
//①try{Thread.sleep(1);}catch (InterruptedException ex){}
while(true) {
int val = at.getValue();
//②try{Thread.sleep(1);}catch (InterruptedException ex){}
if(val % 2 != 0) {
System.out.println(val);
System.exit(0);
}
}
}
} /* Output: (Sample)
191583767
*///:~
上面的代码(①②中的注释是我自己添的) 书上面说不能达到线程同步的效果 因为getValue()没有被synchronized 输出的不应该是101 而应该是191583767或者其他一个很奇怪的数但事实上 我去执行一下上面的代码 输出的确实101 也就是说书上错了吗?然后我分别在①②中加入sleep,按照我的想法, exec.execute(at)执行好之后遇到sleep 然后本来应该挂起的run()开始执行,即 错误产生 输出应该是非101 请问我的解释对吗? 然后书上错了吗?
谢谢
解决方案 »
- Introduction to Java Programming 哪下到bonus chapters
- 关于java浮点型数据计算精确度的问题
- IO读写的本地错误
- JCreator里的一个小问题
- java画布问题
- 谁知道 “Java 2 SDK, Standard Edition v1.4.1 documentation”CHM版下载地址?
- JSP中的include文件在tomcat 5.0 版本中出现乱码,请大虾指点。
- 关于java applet的问题
- 请教jar文件中的manifest.mf有什么用?如何用?
- 什么情况用protect, privat,public?
- java如何调用dll内的特定方法
- XLS 文件乱码
多线程是时间片轮换的,所以我们可以通过加入Thread.yiled()来人为的通知时间片轮换(可能不起效果)
private synchronized void evenIncrement() {
i++;
Thread.yiled();
i++; }
看上面,当某次线程调用完一次i++后就被通知结束,然后main()线程调用getValue()捕获到了只自增了一次
的数字,即奇数,该程序任务完成。
多线程的输出是不可预见的,我不明白LZ想表达些什么。
Thread.yiled() 可以转换时间片 那么sleep可以也可以吗?
我还可以问一个问题吗?
你的理解完全正确 这程序的目的是捕获一个奇数来证明由于getValue()没有被同步而能被随时访问。也就是说,找到了一个奇数(101)程序应该不会终止(书上也那么说的)。
但是 如果执行这个程序 会发现他找到了101就终止了。我就想知道这个是为什么?因为书上说这个程序不会找到101 而会出现一个随即的奇数 比如18923
什么时候会在两个i++之间正好时间片正好轮完,所以说这个奇数是不确定的~
我只能说到这样了~
这话错的 因为它调用了System.exit(0);
只要找到奇数就会退出任务
一个是main线程,另一个是at线程。
at线程,进行循环操作,每次循环做两次++运算。
main线程,在启动at线程后,也做循环操作。
每次循环,都先调用at对象的getValue方法,然后,判断如果是偶数则打印出它的值。谈一下个人理解。
evenIncrement方法,使用了synchronized关键字,那么也就是说,在调用evenIncrement方法的时候,先要争夺at对象的互斥锁。
当获得互斥锁后,才执行evenIncrement的方法体。getValue没有synchronized关键字,那就不用先争夺互斥锁,所以,该方法的返回值,具有不确定性,
有可能是没进行++的值,也有可能进行一次++的值,也有可能是两次++以后的值。如果getValue也带synchronized关键字,那就要先争夺at对象的互斥锁,拿到所以后在进入方法体,执行完方法后释放锁。
这样,其返回值,就不可能是只进行一次++后的值。楼主要明白,main线程,和at线程,他们运行的代码是异步执行的。
在引入互斥锁之后,同样具有异步性,不同在于临界区的代码,成为了原子操作(不可分隔)。