返回信息流package Syncr;
public class Main {
public static void main(String[] args) {
Counter counter=new Counter();
Thread t1=new Thread(new TestThread(counter,1));
Thread t2=new Thread(new TestThread(counter,2));
t1.start();
t2.start();
}
}
class TestThread implements Runnable{
private Counter counter=null;
private int tag=0;
public TestThread(Counter counter,int tag) {
// TODO Auto-generated constructor stub
this.counter=counter;
this.tag=tag;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<10000;i++){
counter.increment();
System.out.println(tag+": "+counter.value());
}
}
}
class Counter {
private static int c=0;
public synchronized void increment(){
c++;
}
public synchronized void decrement(){
c--;
}
public synchronized int value(){
return c;
}
}
输出结果:
....
2: 15858
2: 15859
1: 15813
1: 15861
....
难道不是连续的吗?
这是一条镜像帖。来源:北邮人论坛 / java / #41503同步于 2015/6/9
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖
synchronized怎么不起用呢?
cuter
2015/6/9镜像同步20 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
不是吧,都是基本上连续的:
2: 10
2: 11
2: 12
2: 13
2: 14
2: 15
2: 16
2: 17
2: 18
2: 19
2: 20
2: 21
2: 22
2: 23
2: 24
2: 25
1: 26
1: 27
1: 28
1: 29
1: 31
1: 32
1: 33
1: 34
1: 35
1: 36
【 在 icyfox 的大作中提到: 】
: 因为是两个不同对象的?
虽然increment()和value()两个方法都是同步的,但是在TestThread的run方法中,这两个方法并没有在一个同步块中,所以可能出现一个线程实例访问increment,另一个线程实例访问value方法。
run()可以改成:
public void run() {
for(int i=0;i<10000;i++){
synchronized (TestThread.class) {
counter.increment();
System.out.println(tag+": "+counter.value());
}
}
}
我也刚开始学这些,如有错误,请指出~
synchronized可以保证到最后肯定加了20000次,最后的value应该是20000。 但在increment()和value()之间,值可能会改变,而且两个线程可以交替执行,所以你打出来的值没有理由是连续的。
有点懂了,thx!
【 在 lkasdolka2 的大作中提到: 】
: 虽然increment()和value()两个方法都是同步的,但是在TestThread的run方法中,这两个方法并没有在一个同步块中,所以可能出现一个线程实例访问increment,另一个线程实例访问value方法。
: run()可以改成:
: [code=java]
: ...................
多谢,看来我理解错了。
【 在 nuanyangyang 的大作中提到: 】
: synchronized可以保证到最后肯定加了20000次,最后的value应该是20000。 但在increment()和value()之间,值可能会改变,而且两个线程可以交替执行,所以你打出来的值没有理由是连续的。
一个线程访问increase方法,另一个线程还能访问value方法?
【 在 lkasdolka2 的大作中提到: 】
: 虽然increment()和value()两个方法都是同步的,但是在TestThread的run方法中,这两个方法并没有在一个同步块中,所以可能出现一个线程实例访问increment,另一个线程实例访问value方法。
: run()可以改成:
: [code=java]
: ...................
我这边测试了下,tag和值确实都是乱序的
但是我的疑问是tag乱序没有问题,因为increase和pring方法不是原子的
但是根据同步的“线程可见性”我觉得起码值应该是顺序的,因为increase++后,不管是线程一还是线程二
进入value方法后看到的c应该是最新值,但结果却不是这样,望指点一二
【 在 nuanyangyang 的大作中提到: 】
: synchronized可以保证到最后肯定加了20000次,最后的value应该是20000。 但在increment()和value()之间,值可能会改变,而且两个线程可以交替执行,所以你打出来的值没有理由是连续的。