synchronized初学问题 感兴趣的看下 分不多!!

小小小小小小小白 2014-04-09 05:04:54
package D2;
class People2 extends Thread{
int times;//转账次数
private static int saving = 0;//余额
public People2(String name,int times){
super(name);
this.times = times;
}
public void tansfer(int i){
String name = Thread.currentThread().getName();
synchronized(this){
int sum = saving;
sum+=i;
System.out.println(name+"转账"+i+"元,余额共有"+sum+"元");
saving = sum;
}
}
public void run(){
for(int i=0;i<times;i++){
tansfer(400);
//System.out.println(name);
}
System.out.println(saving);
}
}
public class D3 {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
People2 p1 = new People2("小明",3);
People2 p2 = new People2("小白",4);
p1.setPriority(Thread.MAX_PRIORITY);
p1.start();
p2.start();
}

}
结果如下:
小明转账400元,余额共有400元
小白转账400元,余额共有400元
小明转账400元,余额共有800元
小白转账400元,余额共有800元
小明转账400元,余额共有1200元
1200
小白转账400元,余额共有1200元
小白转账400元,余额共有1600元
1600

这个结果不是我想的答案 我想的答案是想得到 总数的 也就是说 7次转账的总额 2800, 大神门指教下这段代码问题在在哪?怎么改进可以实现我想要的结果!
...全文
162 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
引用 10 楼 kevinlifeng 的回复:
其实你这个可以有两种方法解决。第一种就是同步类而不是对象,因为你的new了两个对象,同步了对象而不是类,他们执行自个的,不会相互互斥。如果想让你能得到你要的结果,可以像2楼的那个样,这样是对的。 还有一种方法解决就是,帮你想要互斥的方法放入一个单独的类中,然后这个类的方法用同步,就可以了,这样引用它的对象,方法都是互斥的。
大概懂了点 谢谢了!
kevinlifeng 2014-04-09
  • 打赏
  • 举报
回复
其实你这个可以有两种方法解决。第一种就是同步类而不是对象,因为你的new了两个对象,同步了对象而不是类,他们执行自个的,不会相互互斥。如果想让你能得到你要的结果,可以像2楼的那个样,这样是对的。 还有一种方法解决就是,帮你想要互斥的方法放入一个单独的类中,然后这个类的方法用同步,就可以了,这样引用它的对象,方法都是互斥的。
  • 打赏
  • 举报
回复
引用 7 楼 awajwgluiawa 的回复:
[quote=引用 5 楼 u013266090 的回复:] [quote=引用 3 楼 lixiaohua886 的回复:] 分析你的代码 private static int saving = 0;//余额 这块代码你初始化的时候,saving都是0; People2 p1 = new People2("小明",3); People2 p2 = new People2("小白",4); 所以,p1.start(); p2.start();这两个线程开始时候都是从 0开始相加; 故:你的出来的值 都是各自单独相加所得 不信 你用这段代码测试下, public static void main(String[] args) throws InterruptedException { People2 p1 = new People2("小明", 3); p1.setPriority(Thread.MAX_PRIORITY); p1.start(); Thread.currentThread().sleep(1000); People2 p2 = new People2("小白", 4);//这样初始化的时候就不是从0开始了 p2.start(); } 运行结果: 小明转账400元,余额共有400元 小明转账400元,余额共有800元 小明转账400元,余额共有1200元 1200 小白转账400元,余额共有1600元 小白转账400元,余额共有2000元 小白转账400元,余额共有2400元 小白转账400元,余额共有2800元 2800 所以你代码问题处在 saving值初始化的问题
看了你写的 为什么 只要让p1对线的线程停一秒 就可以了?能不能从内存的角度来解释下?[/quote]因为这里的线程处理速度很快,停一秒后,其实p1的任务已经完成,同时它也不再调用转账方法,所以p1与p2不是共享互斥资源saving[/quote]我又贴了 一种方式 那种方式 不会出现 刚才的问题,为什么 这种方式不会有这样的问题?谢谢了
  • 打赏
  • 举报
回复
为什么 这种写法 不会出现 这样的问题 !!package D2; //通过实现Runable接口 和synchronized 解决线程同步问题 class Account{ private int saving = 0; synchronized public void tansfer(int i){ String name = Thread.currentThread().getName(); int sum = saving; sum+=i; System.out.println(name+"转账"+i+"元,余额共有"+sum+"元"); saving = sum; } } class People implements Runnable{ Account account; int times; //转账次数 public People(Account account,int times){ this.account = account; this.times = times; } @Override public void run() { // TODO Auto-generated method stub for(int i=0;i<times;i++){ account.tansfer(500); } } } public class D2 { public static void main(String[] args) { // TODO Auto-generated method stub Account account = new Account(); People p1 = new People(account, 4); People p2 = new People(account, 3); Thread thread_p1 = new Thread(p1,"小明"); Thread thread_p2 = new Thread(p2, "小红"); thread_p1.start(); thread_p2.start(); } }结果如下 小明转账500元,余额共有500元 小明转账500元,余额共有1000元 小明转账500元,余额共有1500元 小明转账500元,余额共有2000元 小红转账500元,余额共有2500元 小红转账500元,余额共有3000元 小红转账500元,余额共有3500元
Kenzson 2014-04-09
  • 打赏
  • 举报
回复
引用 5 楼 u013266090 的回复:
[quote=引用 3 楼 lixiaohua886 的回复:] 分析你的代码 private static int saving = 0;//余额 这块代码你初始化的时候,saving都是0; People2 p1 = new People2("小明",3); People2 p2 = new People2("小白",4); 所以,p1.start(); p2.start();这两个线程开始时候都是从 0开始相加; 故:你的出来的值 都是各自单独相加所得 不信 你用这段代码测试下, public static void main(String[] args) throws InterruptedException { People2 p1 = new People2("小明", 3); p1.setPriority(Thread.MAX_PRIORITY); p1.start(); Thread.currentThread().sleep(1000); People2 p2 = new People2("小白", 4);//这样初始化的时候就不是从0开始了 p2.start(); } 运行结果: 小明转账400元,余额共有400元 小明转账400元,余额共有800元 小明转账400元,余额共有1200元 1200 小白转账400元,余额共有1600元 小白转账400元,余额共有2000元 小白转账400元,余额共有2400元 小白转账400元,余额共有2800元 2800 所以你代码问题处在 saving值初始化的问题
看了你写的 为什么 只要让p1对线的线程停一秒 就可以了?能不能从内存的角度来解释下?[/quote]因为这里的线程处理速度很快,停一秒后,其实p1的任务已经完成,同时它也不再调用转账方法,所以p1与p2不是共享互斥资源saving
  • 打赏
  • 举报
回复
引用 5 楼 u013266090 的回复:
[quote=引用 3 楼 lixiaohua886 的回复:] 分析你的代码 private static int saving = 0;//余额 这块代码你初始化的时候,saving都是0; People2 p1 = new People2("小明",3); People2 p2 = new People2("小白",4); 所以,p1.start(); p2.start();这两个线程开始时候都是从 0开始相加; 故:你的出来的值 都是各自单独相加所得 不信 你用这段代码测试下, public static void main(String[] args) throws InterruptedException { People2 p1 = new People2("小明", 3); p1.setPriority(Thread.MAX_PRIORITY); p1.start(); Thread.currentThread().sleep(1000); People2 p2 = new People2("小白", 4);//这样初始化的时候就不是从0开始了 p2.start(); } 运行结果: 小明转账400元,余额共有400元 小明转账400元,余额共有800元 小明转账400元,余额共有1200元 1200 小白转账400元,余额共有1600元 小白转账400元,余额共有2000元 小白转账400元,余额共有2400元 小白转账400元,余额共有2800元 2800 所以你代码问题处在 saving值初始化的问题
看了你写的 为什么 只要让p1对线的线程停一秒 就可以了?能不能从内存的角度来解释下?[/quote]好像理解 了 这种处理方式 不就相当于 2个线程不是同步执行了嘛!
  • 打赏
  • 举报
回复
引用 3 楼 lixiaohua886 的回复:
分析你的代码 private static int saving = 0;//余额 这块代码你初始化的时候,saving都是0; People2 p1 = new People2("小明",3); People2 p2 = new People2("小白",4); 所以,p1.start(); p2.start();这两个线程开始时候都是从 0开始相加; 故:你的出来的值 都是各自单独相加所得 不信 你用这段代码测试下, public static void main(String[] args) throws InterruptedException { People2 p1 = new People2("小明", 3); p1.setPriority(Thread.MAX_PRIORITY); p1.start(); Thread.currentThread().sleep(1000); People2 p2 = new People2("小白", 4);//这样初始化的时候就不是从0开始了 p2.start(); } 运行结果: 小明转账400元,余额共有400元 小明转账400元,余额共有800元 小明转账400元,余额共有1200元 1200 小白转账400元,余额共有1600元 小白转账400元,余额共有2000元 小白转账400元,余额共有2400元 小白转账400元,余额共有2800元 2800 所以你代码问题处在 saving值初始化的问题
看了你写的 为什么 只要让p1对线的线程停一秒 就可以了?能不能从内存的角度来解释下?
木鱼121 2014-04-09
  • 打赏
  • 举报
回复
貌似 是我理解错了 2楼是正解
木鱼121 2014-04-09
  • 打赏
  • 举报
回复
分析你的代码 private static int saving = 0;//余额 这块代码你初始化的时候,saving都是0; People2 p1 = new People2("小明",3); People2 p2 = new People2("小白",4); 所以,p1.start(); p2.start();这两个线程开始时候都是从 0开始相加; 故:你的出来的值 都是各自单独相加所得 不信 你用这段代码测试下, public static void main(String[] args) throws InterruptedException { People2 p1 = new People2("小明", 3); p1.setPriority(Thread.MAX_PRIORITY); p1.start(); Thread.currentThread().sleep(1000); People2 p2 = new People2("小白", 4);//这样初始化的时候就不是从0开始了 p2.start(); } 运行结果: 小明转账400元,余额共有400元 小明转账400元,余额共有800元 小明转账400元,余额共有1200元 1200 小白转账400元,余额共有1600元 小白转账400元,余额共有2000元 小白转账400元,余额共有2400元 小白转账400元,余额共有2800元 2800 所以你代码问题处在 saving值初始化的问题
Kenzson 2014-04-09
  • 打赏
  • 举报
回复
上面的方法不是很明智,可以这样来
    public void tansfer(int i) {
        String name = Thread.currentThread().getName();
        synchronized (People2.class) {
            int sum = saving;
            sum += i;
            System.out.println(name + "转账" + i + "元,余额共有" + sum + "元");
            saving = sum;
        }
    }
Kenzson 2014-04-09
  • 打赏
  • 举报
回复
走的太快,可以这样。
        try {
            Thread.sleep(100);
        } catch (InterruptedException ex) {
            Logger.getLogger(SubClass.class.getName()).log(Level.SEVERE, null, ex);
        }

62,612

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧