有个Bank类, 属性money=0;然后创建三个线程,调用addmoney()往bank里面加钱,
我这样写,为什么不能同步呢 ? 结果不是300万呀?新手请指教.
public class Bank {
private int money=0;
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public void addMoney(int money){
this.money+=money;
}
public void subMoney(int money){
this.money-=money;
}
}
public class test2 implements Runnable {
private Bank bank;
public test2(Bank bank) {
this.bank = bank;
}
@Override
public synchronized void run() {
for (int i = 0; i < 1000; i++) {
bank.addMoney(1000);
}
}
public static void main(String[] args) {
Bank bank = new Bank();
test2 r1 = new test2(bank);
test2 r2 = new test2(bank);
test2 r3 = new test2(bank);
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
Thread t3 = new Thread(r3);
t1.start();
t2.start();
t3.start();
System.out.println(bank.getMoney());
}
}
如有我现在用同一个runable实例去构造线程,结果就很明显了。
[code="java"]Thread t1 = new Thread(r1);
Thread t2 = new Thread(r1);
Thread t3 = new Thread(r1);
t1.start();
t2.start();
t3.start();
System.out.println(bank.getMoney());[/code]
输出:
[quote]0
Thread-0:befor:2014-07-29 11:19:34.000034:$0
Thread-0:after:2014-07-29 11:19:34.000034:$1000
Thread-0:befor:2014-07-29 11:19:34.000034:$1000
Thread-0:after:2014-07-29 11:19:34.000034:$2000
Thread-0:befor:2014-07-29 11:19:34.000034:$2000
Thread-0:after:2014-07-29 11:19:34.000034:$3000
Thread-0:befor:2014-07-29 11:19:34.000034:$3000
Thread-0:after:2014-07-29 11:19:34.000034:$4000
Thread-0:befor:2014-07-29 11:19:34.000034:$4000
Thread-0:after:2014-07-29 11:19:34.000034:$5000
Thread-0:befor:2014-07-29 11:19:34.000034:$5000
Thread-0:after:2014-07-29 11:19:34.000034:$6000
Thread-0:befor:2014-07-29 11:19:34.000034:$6000
Thread-0:after:2014-07-29 11:19:34.000034:$7000
Thread-0:befor:2014-07-29 11:19:34.000034:$7000
Thread-0:after:2014-07-29 11:19:34.000034:$8000
Thread-0:befor:2014-07-29 11:19:34.000034:$8000
Thread-0:after:2014-07-29 11:19:34.000034:$9000
Thread-0:befor:2014-07-29 11:19:34.000034:$9000
Thread-0:after:2014-07-29 11:19:34.000034:$10000
Thread-2:befor:2014-07-29 11:19:34.000034:$10000
Thread-2:after:2014-07-29 11:19:34.000034:$11000
Thread-2:befor:2014-07-29 11:19:34.000034:$11000
Thread-2:after:2014-07-29 11:19:34.000034:$12000
Thread-2:befor:2014-07-29 11:19:34.000034:$12000
Thread-2:after:2014-07-29 11:19:34.000034:$13000
Thread-2:befor:2014-07-29 11:19:34.000034:$13000
Thread-2:after:2014-07-29 11:19:34.000034:$14000
Thread-2:befor:2014-07-29 11:19:34.000034:$14000
Thread-2:after:2014-07-29 11:19:34.000034:$15000
Thread-2:befor:2014-07-29 11:19:34.000034:$15000
Thread-2:after:2014-07-29 11:19:34.000034:$16000
Thread-2:befor:2014-07-29 11:19:34.000034:$16000
Thread-2:after:2014-07-29 11:19:34.000034:$17000
Thread-2:befor:2014-07-29 11:19:34.000034:$17000
Thread-2:after:2014-07-29 11:19:34.000034:$18000
Thread-2:befor:2014-07-29 11:19:34.000034:$18000
Thread-2:after:2014-07-29 11:19:34.000034:$19000
Thread-2:befor:2014-07-29 11:19:34.000034:$19000
Thread-2:after:2014-07-29 11:19:34.000034:$20000
Thread-1:befor:2014-07-29 11:19:34.000034:$20000
Thread-1:after:2014-07-29 11:19:34.000034:$21000
Thread-1:befor:2014-07-29 11:19:34.000034:$21000
Thread-1:after:2014-07-29 11:19:34.000034:$22000
Thread-1:befor:2014-07-29 11:19:34.000034:$22000
Thread-1:after:2014-07-29 11:19:34.000034:$23000
Thread-1:befor:2014-07-29 11:19:34.000034:$23000
Thread-1:after:2014-07-29 11:19:34.000034:$24000
Thread-1:befor:2014-07-29 11:19:34.000034:$24000
Thread-1:after:2014-07-29 11:19:34.000034:$25000
Thread-1:befor:2014-07-29 11:19:34.000034:$25000
Thread-1:after:2014-07-29 11:19:34.000034:$26000
Thread-1:befor:2014-07-29 11:19:34.000034:$26000
Thread-1:after:2014-07-29 11:19:34.000034:$27000
Thread-1:befor:2014-07-29 11:19:34.000034:$27000
Thread-1:after:2014-07-29 11:19:34.000034:$28000
Thread-1:befor:2014-07-29 11:19:34.000034:$28000
Thread-1:after:2014-07-29 11:19:34.000034:$29000
Thread-1:befor:2014-07-29 11:19:34.000034:$29000
Thread-1:after:2014-07-29 11:19:34.000034:$30000
[/quote]
synchronized(bank) {
// .....
}
首先楼主没有理解线程的概念,start();只是启动线程,有没有结束另说呢,这里肯定是得不到的300w。如果在输出上方加上如下3句话后,是可以得到300w的数据的。[code="java"]
t1.join();
t2.join();
t3.join();
[/code]
第二个问题,同步的问题,我该写了你的代码test2 类,你自己看看吧,看看能不能直观的看到问题:
[code="java"]
import java.text.SimpleDateFormat;
import java.util.Date;
public class test2 implements Runnable {
public static SimpleDateFormat f = new SimpleDateFormat(
"yyyy-MM-dd hh:mm:ss.ssssss");
private Bank bank;
public test2(Bank bank) {
this.bank = bank;
}
public synchronized void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+":befor:"+f.format(new Date())+":$"+bank.getMoney());
bank.addMoney(1000);
System.out.println(Thread.currentThread().getName()+":after:"+f.format(new Date())+":$"+bank.getMoney());
}
}
public static void main(String[] args) throws InterruptedException {
Bank bank = new Bank();
test2 r1 = new test2(bank);
test2 r2 = new test2(bank);
test2 r3 = new test2(bank);
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
Thread t3 = new Thread(r3);
t1.start();
t2.start();
t3.start();
System.out.println(bank.getMoney());
}
}[/code]
输出:[quote]0
Thread-0:befor:2014-07-29 11:09:06.000006:$0
Thread-0:after:2014-07-29 11:09:06.000006:$1000
Thread-0:befor:2014-07-29 11:09:06.000006:$1000
Thread-0:after:2014-07-29 11:09:06.000006:$2000
Thread-0:befor:2014-07-29 11:09:06.000006:$2000
Thread-0:after:2014-07-29 11:09:06.000006:$3000
Thread-0:befor:2014-07-29 11:09:06.000006:$3000
Thread-0:after:2014-07-29 11:09:06.000006:$4000
Thread-0:befor:2014-07-29 11:09:06.000006:$4000
Thread-0:after:2014-07-29 11:09:06.000006:$5000
Thread-0:befor:2014-07-29 11:09:06.000006:$5000
Thread-0:after:2014-07-29 11:09:06.000006:$6000
Thread-2:befor:2014-07-29 11:09:06.000006:$5000
Thread-0:befor:2014-07-29 11:09:06.000006:$6000
Thread-2:after:2014-07-29 11:09:06.000006:$8000
Thread-0:after:2014-07-29 11:09:06.000006:$8000
Thread-0:befor:2014-07-29 11:09:06.000006:$8000
Thread-0:after:2014-07-29 11:09:06.000006:$9000
Thread-0:befor:2014-07-29 11:09:06.000006:$9000
Thread-0:after:2014-07-29 11:09:06.000006:$10000
Thread-0:befor:2014-07-29 11:09:06.000006:$10000
Thread-0:after:2014-07-29 11:09:06.000006:$11000
Thread-1:befor:2014-07-29 11:09:06.000006:$11000
Thread-1:after:2014-07-29 11:09:06.000006:$12000
Thread-2:befor:2014-07-29 11:09:06.000006:$8000
Thread-2:after:2014-07-29 11:09:06.000006:$13000
Thread-2:befor:2014-07-29 11:09:06.000006:$13000
Thread-2:after:2014-07-29 11:09:06.000006:$14000
Thread-2:befor:2014-07-29 11:09:06.000006:$14000
Thread-2:after:2014-07-29 11:09:06.000006:$15000
Thread-2:befor:2014-07-29 11:09:06.000006:$15000
Thread-2:after:2014-07-29 11:09:06.000006:$16000
Thread-2:befor:2014-07-29 11:09:06.000006:$16000
Thread-2:after:2014-07-29 11:09:06.000006:$17000
Thread-2:befor:2014-07-29 11:09:06.000006:$17000
Thread-2:after:2014-07-29 11:09:06.000006:$18000
Thread-2:befor:2014-07-29 11:09:06.000006:$18000
Thread-2:after:2014-07-29 11:09:06.000006:$19000
Thread-2:befor:2014-07-29 11:09:06.000006:$19000
Thread-2:after:2014-07-29 11:09:06.000006:$20000
Thread-2:befor:2014-07-29 11:09:06.000006:$20000
Thread-2:after:2014-07-29 11:09:06.000006:$21000
Thread-1:befor:2014-07-29 11:09:06.000006:$17000
Thread-1:after:2014-07-29 11:09:06.000006:$22000
Thread-1:befor:2014-07-29 11:09:06.000006:$22000
Thread-1:after:2014-07-29 11:09:06.000006:$23000
Thread-1:befor:2014-07-29 11:09:06.000006:$23000
Thread-1:after:2014-07-29 11:09:06.000006:$24000
Thread-1:befor:2014-07-29 11:09:06.000006:$24000
Thread-1:after:2014-07-29 11:09:06.000006:$25000
Thread-1:befor:2014-07-29 11:09:06.000006:$25000
Thread-1:after:2014-07-29 11:09:06.000006:$26000
Thread-1:befor:2014-07-29 11:09:06.000006:$26000
Thread-1:after:2014-07-29 11:09:06.000006:$27000
Thread-1:befor:2014-07-29 11:09:06.000006:$27000
Thread-1:after:2014-07-29 11:09:06.000006:$28000
Thread-1:befor:2014-07-29 11:09:06.000006:$28000
Thread-1:after:2014-07-29 11:09:06.000006:$29000
Thread-1:befor:2014-07-29 11:09:06.000006:$29000
Thread-1:after:2014-07-29 11:09:06.000006:$30000[/quote]
最后罗嗦一句,不给我分 天理不容的 打了这么多字 我tmd太有奉献精神了
如果把money改为static呢?
你的思维是一个线程一个线程的跑 最后数据累加 执行main方法打印出来,
因为run方法加了锁 所以在有线程进入的时候 另外的线程好像是不能进去 要等待这个线程执行完 释放资源 然后第二个线程进入直到第三个线程
而你又用的是main是主线程所以在你执行完第一个 main方法就开始执行没有等另外的线程走完 而直接打印数据,只需要在main加入 join 等待线程每个线程执行完成 打印的就是最后的数据累加
修改代码如下:
package cn.com.wangxiuwei.test;
public class test2 implements Runnable{
private Bank bank;
public test2(Bank bank) {
this.bank = bank;
}
public synchronized void run() {
for (int i = 0; i < 1000; i++) {
bank.addMoney(1000);
}
}
public static void main(String[] args) throws InterruptedException {
Bank bank = new Bank();
test2 r1 = new test2(bank);
test2 r2 = new test2(bank);
test2 r3 = new test2(bank);
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
Thread t3 = new Thread(r3);
t1.start();
[color=red]t1.join();[/color]
t2.start();
[color=red]t2.join();[/color]
t3.start();
[color=red]t3.join();[/color]
System.out.println(bank.getMoney());
}
}
采纳就采纳 rmzdb 这个小伙解决问题很积极 精神值得我们学习 呵呵
我觉得楼主还是先去把,同步和synchronized看下.
1.线程和线程调用类/方法/字段 没有关联关系
2.你只需要对调用类/方法/字段 加上安全锁就行了
3.至于实现,楼上给出了.百度一大堆
synchronized 为什么加载 线程里面的run上面了?
应该加在addMoney()吧。