谢谢 经过楼上提醒 我把代码改成了这样 问题貌似解决了 但是又有一个新问题了,我把Count类中的synchronized去掉,打印的结果居然跟同步的一模一样。这样怎么才能区分出synchronized的同步性呢? class ThreadTest implements Runnable { Count c = new Count(); @Override public void run() { c.increase(); System.out.println(c.getValue()); }
public void print() { } }
不知道你的代码想实现一个什么功能。 new Thread(a).start(); a.print(); 这两行什么意思啊?完全没有体现多线程与同步的思想啊。 你在一个线程里面实现count+1,在主线程里面调用print方法,有什么意义呢?如下是我修改了你的代码,同时给你一个,我写的一个例子。希望对你有帮助。 public class Test22{
public static void main(String[ ] args) { ThreadTest a = new ThreadTest(); for(int i=0;i<100;i++){ new Thread(a).start(); // a.print(); }
} }
class ThreadTest implements Runnable { Count c = new Count();
public void run() { c.increase(); }
// public void print() { // System.out.println(c.getValue()); // } }
final class Count { private long value = 0;
public synchronized long getValue() { return value; }
public synchronized long increase() { if(value == Long.MAX_VALUE) { throw new IllegalStateException("error"); } System.out.println(++value); return value; } }public class VolatileTest { static Integer count = 0;
for (int i = 0; i < 1000; i++) { Thread thread = new Thread(group,""){ public void run() { addCount(); addCountVolatile(); addCountSynchronizedMethod(); addCountSynchronizedAttribute(); } };
private long value = 0; 我虽然不太清楚楼主的意图,但我觉得问题出在value字段 这是一个成员变量,每个对象都有自己独立的堆内存空间,而每个对象的value值都是从0开始,所以肯定会有重复的值 解决办法: 设置成静态变量,那么只会在类中维持一份拷贝 private staticf long value = 0;
class ThreadTest implements Runnable {
Count c = new Count(); @Override
public void run() {
c.increase();
System.out.println(c.getValue());
}
public void print() {
}
}
new Thread(a).start();
a.print();
这两行什么意思啊?完全没有体现多线程与同步的思想啊。
你在一个线程里面实现count+1,在主线程里面调用print方法,有什么意义呢?如下是我修改了你的代码,同时给你一个,我写的一个例子。希望对你有帮助。
public class Test22{
public static void main(String[ ] args) {
ThreadTest a = new ThreadTest();
for(int i=0;i<100;i++){
new Thread(a).start();
// a.print();
}
}
}
class ThreadTest implements Runnable {
Count c = new Count();
public void run() {
c.increase();
}
// public void print() {
// System.out.println(c.getValue());
// }
}
final class Count {
private long value = 0;
public synchronized long getValue() {
return value;
}
public synchronized long increase() {
if(value == Long.MAX_VALUE) {
throw new IllegalStateException("error");
}
System.out.println(++value);
return value;
}
}public class VolatileTest { static Integer count = 0;
static volatile Integer countVolatile = 0;
static Integer countSynchronizedMethod = 0;
static Integer countSynchronizedAttribute = 0;
static void addCount(){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
count ++;
}
static void addCountVolatile(){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
countVolatile ++;
}
static synchronized void addCountSynchronizedMethod(){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
countSynchronizedMethod ++;
}
static void addCountSynchronizedAttribute(){
synchronized(countSynchronizedAttribute){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
countSynchronizedAttribute ++;
}
}
/**
* 功能:
* @param args
*/
public static void main(String[] args) {
ThreadGroup group = new ThreadGroup("test");
for (int i = 0; i < 1000; i++) {
Thread thread = new Thread(group,""){
public void run() {
addCount();
addCountVolatile();
addCountSynchronizedMethod();
addCountSynchronizedAttribute();
}
};
thread.start();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("count:" + count);
System.out.println("countVolatile:" + countVolatile);
System.out.println("countSynchronized:" + countSynchronizedMethod);
System.out.println("countSynchronizedAttribute:" + countSynchronizedAttribute);
}}
我虽然不太清楚楼主的意图,但我觉得问题出在value字段
这是一个成员变量,每个对象都有自己独立的堆内存空间,而每个对象的value值都是从0开始,所以肯定会有重复的值
解决办法:
设置成静态变量,那么只会在类中维持一份拷贝
private staticf long value = 0;
后来的代码中出现加不加synchronized关键字都一样的情况其实只是错觉.因为你电脑够快, 所以每次运行的时候都是直接过掉了. 如果你的代码在run方法里面的increae()方法和System.out.println()中间加上其他代码的话就有可能引起打印数据异常的情况. 所以还是要添加synchronized关键字
另外, 您这个程序中虽然可以保证每次都打印从1~100, 但是你没法保证打印出来的数字的顺序.
这一点你可以在run()方法两行代码中加入一个for循环(1~100的循环就够了)就可以看出来.
public void run() {
synchronized (c) { // 这里是关键,把(动作1,动作2)同步
// 这意味着,在动作1和动作2之间,别的线程插不进来
c.increase(); // 动作1
try {
Thread.currentThread().sleep(100); // Sleep 加强观察效果
} catch (InterruptedException e) {}
System.out.println(c.getValue()); // 动作2
}
}// 方案2:无同步
public void run() {
c.increase(); // 动作1
try {
Thread.currentThread().sleep(100); // Sleep 加强观察效果
} catch (InterruptedException e) {}
System.out.println(c.getValue()); // 动作2
}
另外,// 方案1 :同步
public void run() {
synchronized (c) {
//...body
}
}// 等同于:
public synchronized void run() {
//...body
}
http://ifeve.com/who-is-lock/
http://ifeve.com/race-conditions-and-critical-sections/
http://ifeve.com/locks/
a.print();
这两句的执行顺序没法保证吧```