写了一段代码,预期变量serialNum增加到10000就停止,可是每次结束的时候,serialNum的结果都是10000多好几百,不知为何,望大家指教。public class Test implements Runnable {
/**
* 序列号
*/
private static int serialNum = 0;
/**
* 测试
*/
public void run() {
this.increase();
}
private synchronized void increase() {
while (Test.serialNum < 10000) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
Test.serialNum++;
System.out.println("现在的值为:" + Test.serialNum);
}
}
/**
* @param args
*/
public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
new Thread(new Test()).start();
}
}
}控制台输出结果:
…… ……
现在的值为:10992
现在的值为:10993
现在的值为:10994
现在的值为:10995
现在的值为:10996
现在的值为:10997
现在的值为:10998
/**
* 序列号
*/
private static int serialNum = 0;
/**
* 测试
*/
public void run() {
this.increase();
}
private synchronized void increase() {
while (Test.serialNum < 10000) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
Test.serialNum++;
System.out.println("现在的值为:" + Test.serialNum);
}
}
/**
* @param args
*/
public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
new Thread(new Test()).start();
}
}
}控制台输出结果:
…… ……
现在的值为:10992
现在的值为:10993
现在的值为:10994
现在的值为:10995
现在的值为:10996
现在的值为:10997
现在的值为:10998
解决方案 »
- JAVA SE GridBagLayout 问题
- 求大神解析xml
- 请问java中所有的抽象类都要用 implements吗?
- 关于webwork很难的问题
- thinking in java(中文)第93页
- 怎么做模糊查询呢?
- java那个控件能够实现多行文本不同颜色显示
- System.exit(?)的用法?
- 不知那位有qt2.0 for window,在什么地方可以下载?
- 谁有用于ms sqlserver 7.0/2000的支持jdbc2.0的驱动程序?
- JComboBox为可编辑时为什么不能每按下一个键就反应一次???在线等!!!!!!!!!!!!急急急>>>>>>>>>>
- 请帮我看看这道笔试题吧。
for (int i = 0; i < 1000; i++) {
Thread t=new Thread(new Test());
t.start();
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
你这样的原因在于循环内,每一次都是new出一个对象,synchronized 的锁每new一次就是一个。你这样的写法等于没有同步, 需要一个系统及的单例来当这把锁,比如:
sychronized (SystemLock) {
Test.serialNum++;
System.out.println("现在的值为:" + Test.serialNum);
}SystemLock 是一个系统级的单例, 虽然加法时也是顺序执行,但作用范围较一楼来的小
private static Object lock;public increase(){
sychronized(lock){
.....
}
}建议参看:http://blog.csdn.net/Iangao/archive/2008/10/09/3041265.aspx
private void increase() {
int myNumber;
while ((myNumber=serialNum++) < 10000) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("现在的值为:" + myNumber);
}
}如果一定要分开的话,就必须把整个while放到lock中同步了,否则比较时的serial和自增时的serial一定是不同的.
public class Test implements Runnable {
/**
* 序列号
*/
private static Integer serialNum = 0;
/**
* 测试
*/
public void run() {
this.increase();
}
private void increase() {
synchronized(Test.serialNum) {
while (Test.serialNum < 10000) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
Test.serialNum++;
System.out.println("现在的值为:" + Test.serialNum);
}
}
}
/**
* @param args
*/
public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
new Thread(new Test()).start();
}
}
}控制台输出:
…… ……
现在的值为:10000
现在的值为:10000
现在的值为:10001
现在的值为:10002
现在的值为:10003
现在的值为:10004
现在的值为:10005
现在的值为:10006
现在的值为:10007我的代码是在eclipse里边调试的,刚刚发现一个奇怪的问题:Run的速度很慢,Debug的速度很快,不知道为什么。
2. 上述问题可以按照下面两种方法解决
A. 再把increase()声明成静态同步方法,同时去掉synchronized(Test.serialNum)这时就没用了
B. 如果increase不能改成静态的.建议还是使用信号量吧,如下:
private static Semaphore s=new Semaphore(1)
private void increase(){
s.p();
while(..){
...
}
s.v();
}
上述两种均已测试通过,请验证
3. 正如2楼所说的, 其实这个例子中的同步只起到阻塞做用,并没有同步的执行.因为在执行完10000条循环前同步锁并没有释放.只在一个线程中进行着. 如果是实际应用,建议再细化同步临界区,否则是很难实现同步的.