黑马程序员技术交流社区

标题: 关于线程、同步、锁的一个问题 [打印本页]

作者: 匡文    时间: 2013-10-21 17:11
标题: 关于线程、同步、锁的一个问题
本帖最后由 匡文 于 2013-10-21 17:44 编辑

是毕老师视频中讲解线程的一个例子,我按着他的思路敲的代码,同步的语句加了锁(obj),但是仍然没能同步
  1. class Bank{
  2.         private int sum;
  3.         public void add(int i){
  4.                 Object obj = new Object();
  5.                 synchronized (obj){
  6.                         sum = sum + i;
  7.                         try{
  8.                                 Thread.sleep(100);
  9.                         }catch(Exception e){
  10.                         }
  11.                         System.out.println(Thread.currentThread().getName()+"sum= " + sum);
  12.                 }
  13.         }
  14. }

  15. class Cus implements Runnable{
  16.         private Bank b = new Bank();
  17.         public void run(){
  18.                 for(int i=0;i<3;i++){
  19.                         b.add(100);
  20.                 }
  21.         }
  22. }

  23. class TestBank{
  24.         public static void main(String[] args){
  25.                 Cus c = new Cus();
  26.                
  27.                 Thread t1 = new Thread(c);
  28.                 Thread t2 = new Thread(c);
  29.                 t1.start();
  30.                 t2.start();
  31.         }
  32. }
复制代码
按理说加了锁之后,无论运行多少次,输出结果都应该是
Thread-0sum= 100
Thread-1sum= 200
Thread-0sum= 400
Thread-1sum= 500
Thread-0sum= 600
Thread-1sum= 600


但是,上面代码输出结果偶尔仍然是:
Thread-0sum= 200
Thread-1sum= 200
Thread-0sum= 400
Thread-1sum= 500
Thread-0sum= 600
Thread-1sum= 600

“200”出现了2次,“100”没有出现,说明还是存在线程安全问题。。。但是我已经加锁了的呀,这是为什么?



作者: kellyzyb    时间: 2013-10-21 17:23
  1. class Bank{
  2.         private int sum;
  3.         public synchronized void add(int i)
  4.         {
  5.                  sum = sum + i;
  6.                         try
  7.                         {
  8.                             Thread.sleep(100);
  9.                             System.out.println(Thread.currentThread().getName()+"sum= " + sum);
  10.                         }catch(Exception e)
  11.                         {
  12.                                
  13.                         }
  14.                
  15.         }
  16. }

  17. class Cus implements Runnable{
  18.         private Bank b = new Bank();
  19.         public void run(){
  20.                 for(int i=0;i<3;i++){
  21.                         b.add(100);
  22.                 }
  23.         }
  24. }

  25. class TestBank{
  26.         public static void main(String[] args){
  27.                 Cus c = new Cus();
  28.                
  29.                 Thread t1 = new Thread(c);
  30.                 Thread t2 = new Thread(c);
  31.                 t1.start();
  32.                 t2.start();
  33.         }
  34. }
复制代码

作者: 匡文    时间: 2013-10-21 17:26
kellyzyb 发表于 2013-10-21 17:23

你这是改成同步函数了,也行。。。但是我想知道,我那样同步代码块为什么会错。。。
作者: kellyzyb    时间: 2013-10-21 17:30
上面是我改的代码,针对你的代码的话,问题:要保证锁的唯一性。  b.add(100);这个方法每个线程去访问这个add这个方法,都会创建一个Object 。持有两把锁怎么能安全呢?下面是我改的原代码。
  1. class Bank{
  2.         private int sum;
  3.         Object obj = new Object();
  4.         public void add(int i){
  5.                
  6.                 synchronized (obj)
  7.                 {
  8.                         sum = sum + i;
  9.                         try
  10.                         {
  11.                             Thread.sleep(100);
  12.                             System.out.println(Thread.currentThread().getName()+"sum= " + sum);
  13.                         }catch(Exception e)
  14.                         {
  15.                                
  16.                         }
  17.                         
  18.                 }
  19.         }
  20. }

  21. class Cus implements Runnable{
  22.         private Bank b = new Bank();
  23.         public void run(){
  24.                 for(int i=0;i<3;i++){
  25.                         b.add(100);
  26.                 }
  27.         }
  28. }

  29. class TestBank{
  30.         public static void main(String[] args){
  31.                 Cus c = new Cus();
  32.                
  33.                 Thread t1 = new Thread(c);
  34.                 Thread t2 = new Thread(c);
  35.                 t1.start();
  36.                 t2.start();
  37.         }
  38. }
复制代码

作者: 黑马-马磊    时间: 2013-10-21 17:40
本帖最后由 黑马-马磊 于 2013-10-21 17:44 编辑

Object obj = new Object();
定义的位置不对!
我的找出问题的步骤:
确定是2个或者2歌以上的线程参与运行,那么只能是锁出现了问题(是不是同一把锁)。按照你的写法是每次都用都会创建一个锁,不是唯一的。要把锁提出来!
希望遇到类似的问题能够参加毕老师总结的方法解决问题

作者: 匡文    时间: 2013-10-21 17:43
kellyzyb 发表于 2013-10-21 17:30
上面是我改的代码,针对你的代码的话,问题:要保证锁的唯一性。  b.add(100);这个方法每个线程去访问这个a ...

哦。。。。明白了,每个线程都会创建一次,我锁定义错地方了:o,谢谢
作者: 匡文    时间: 2013-10-21 17:43
黑马-马磊 发表于 2013-10-21 17:40
Object obj = new Object();
定义的位置不对!
我的找出问题的步骤:

嗯,谢谢提醒
作者: 马晓平    时间: 2013-10-21 23:08
你写错了吧,首先你Object obj = new Object();这句都写错位置了吧




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2