黑马程序员技术交流社区

标题: 同步代码块的问题 [打印本页]

作者: 黄燕京    时间: 2012-5-18 22:12
标题: 同步代码块的问题
按毕老师的代码输的,使用同步代码块后就出问题了。
class ticket implements Runnable//定义类实现Runnable接口
{
private int tick=100;
public void run()    //2覆盖Runnable接口中的方法
{
  Object obj=new Object();
  while (true)
  {
   synchronized (obj)//同步代码块
   {
   if (tick>0)
   {
    try{Thread.sleep(2);}
    catch (Exception e){}
    System.out.println(Thread.currentThread().getName()+"........sale:"+tick--);
   }
   }
  
  }
      
}
}
class  ticketDemo
{
public static void main(String[] args)
{
ticket t=new ticket();
Thread t1=new Thread(t); //通过Thread类建立线程对象。将Run那边了接口的子类对象作为实际参数传递给Thread类的构造函数。
Thread t2=new Thread(t);
Thread t3=new Thread(t);
Thread t4=new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();//调用Thread类的start方法开启线程并调用Runnable接口子类的run方法
}
}

同步代码块.jpg (44.46 KB, 下载次数: 11)

同步代码块.jpg

作者: 褚代江    时间: 2012-5-18 22:31
你是不是把代码写错了啊
  1. class ticket implements Runnable//定义类实现Runnable接口
  2. {
  3.         private int tick=100;
  4.         public void run()    //2覆盖Runnable接口中的方法
  5.         {
  6.                 Object obj=new Object();
  7.                 while (tick>0)//这个地方先判断是否大于0在循环把
  8.                 {
  9.                         synchronized (obj)//同步代码块
  10.                         {
  11.                                 if (true)//可以删除的
  12.                                 {
  13.                                 //    try{Thread.sleep(2000);
  14.                                 //        }catch (Exception e){}
  15.                                         System.out.println(Thread.currentThread().getName()+"........sale:"+tick--);
  16.                                 }
  17.                         }
  18.                 }
  19.         }
  20. }
  21. class  ticketDemo
  22. {
  23.         public static void main(String[] args)
  24.         {
  25.                 ticket t=new ticket();
  26.                 Thread t1=new Thread(t);
  27.                 Thread t2=new Thread(t);
  28.                 Thread t3=new Thread(t);
  29.                 Thread t4=new Thread(t);
  30.                 t1.start();
  31.                 t2.start();
  32.                 t3.start();
  33.                 t4.start();
  34.         }
  35. }
复制代码

作者: 周素强    时间: 2012-5-18 22:59
本帖最后由 周素强 于 2012-5-18 23:02 编辑

while (tick>0)//这个地方先判断是否大于0在循环把
{
        try{Thread.sleep(2000);
        }catch (Exception e){}
        synchronized (obj)//同步代码块
       {
               System.out.println(Thread.currentThread().getName()+"........sale:"+tick--);
       }
}
作者: 贠(yun)靖    时间: 2012-5-18 23:09
褚代江 发表于 2012-5-18 22:31
你是不是把代码写错了啊

你的也错了啊,小褚啊   while循环要在synchronized里面的  
package my.test;

public class TestTTT {
        public static void main(String[] args) {
                // TODO Auto-generated method stub
                 ticket t=new ticket();
         Thread t1=new Thread(t);
         Thread t2=new Thread(t);
         Thread t3=new Thread(t);
         Thread t4=new Thread(t);
         t1.start();
         t2.start();
         t3.start();
         t4.start();
        }
}
class ticket implements Runnable
{
                Object obj=new Object();
        private int tick=100;
        public void run()
        {
                synchronized (this)
                {
                while (tick>0)
                {
                     try{Thread.sleep(100);
                       }catch (Exception e){}
                     System.out.println(Thread.currentThread().getName()+"........sale:"+tick--);                              
                }
                }
        }
}

作者: 袁錦泰    时间: 2012-5-19 00:16
本帖最后由 袁錦泰 于 2012-5-19 00:44 编辑
  1. private int tick = 100;

  2.     Object obj = new Object();//将锁对象写到成员位置

  3.     public void run() {
  4.         while (true) {
  5.             synchronized (obj) {
复制代码
首先我要和你再次说明一下同步的前提:
1.具备多个线程
2.使用同一个锁(obj)
你的程序违背了原则中的第二点,每个线程开启后都具备了自己的run()方法,每个run()方法中都有一个局部变量Object obj = new Object();这就表明每个线程都有自己的锁,你开启了四个线程就具备了四把锁,从而导致无法同步.
然后我说一下解决方法:
将Objcet obj = new Oject();语句放在同步run()方法外,因为obj在Ticket t对象中变为成员变量,与tick的属性相同,都变为了被共享的成员,就是这个导致你的线程代码加上同步之后依然无法解决线程安全问题的原因.
最后我要和你强调的是代码的书写格式与标识符的书写规范,类名首字母需要大写,代码格式需要有层次感,其他我就不再赘述了.
不知是否解释的够清楚,如果还不明白就再联系我!
作者: 袁錦泰    时间: 2012-5-19 00:21
本帖最后由 袁錦泰 于 2012-5-19 00:24 编辑
贠(yun)靖 发表于 2012-5-18 23:09
你的也错了啊,小褚啊   while循环要在synchronized里面的  
package my.test;

他没有写错. 循环内部才是线程需要执行的代码,也就是需要被同步的代码.
作者: niceBoy    时间: 2012-5-19 08:35
哟西,楼上的说的完整了,我能不能复制下给个分
1.具备多个线程
2.使用同一个锁(obj)
你的程序违背了原则中的第二点,每个线程开启后都具备了自己的run()方法,每个run()方法中都有一个局部变量Object obj = new Object();这就表明每个线程都有自己的锁,你开启了四个线程就具备了四把锁,从而导致无法同步.
作者: 贠(yun)靖    时间: 2012-5-19 10:20
袁錦泰 发表于 2012-5-19 00:21
他没有写错. 循环内部才是线程需要执行的代码,也就是需要被同步的代码.


哥们 你看清楚两个的不同之处,他写的是在while里面判断退出循环的条件的  
以他那种写法  当线程1 在sleep了  这时候 tick还没有执行自减呢   那么其他线程是不是就可以进入while循环了?  等待在synchronized块的外面
  假设这时候tick为1的时候  synchronized外面有3个线程都在等待  那么接下来   当线程1执行完的时候 释放了锁
  其他线程一次进来执行代码   最终会导致 -1 -2的票数   
  不信你可以把他的代码测试一下    sleep一下   结果就出来了

作者: 袁錦泰    时间: 2012-5-19 11:54
本帖最后由 袁錦泰 于 2012-5-19 12:09 编辑
贠(yun)靖 发表于 2012-5-19 10:20
哥们 你看清楚两个的不同之处,他写的是在while里面判断退出循环的条件的  
以他那种写法  当线程1 在s ...

首先抱歉,昨天太晚了,所以我没有认真看他写得代码,就随便否定了你的回答,实在不好意思。
然后是他的代码错误不止一处,和提问题的人犯了同样的错误,而且判断条件写得也有问题。
最后我想和你说说你的解决方案,你的解决方案的确是正确的,问题分析的也很到位,但是我有一点想请教,我的对你答案的理解是如果在循环上面就加锁,那这岂不是就变成单线程了?还没有通过代码验证,如果分析的不对还请指正,外加可以的话把你QQ号告诉我。
作者: 贠(yun)靖    时间: 2012-5-19 12:17
袁錦泰 发表于 2012-5-19 11:54
首先抱歉,昨天太晚了,所以我没有认真看他写得代码,就随便否定了你的回答,实在不好意思。
然后是他的代 ...

是啊,如果是推出条件要写到while(tickt>0) 这样的话  synchronized必须写到while的外面才能保证同步
      那么这时候 就是你分析的那样,始终导致只有一个线程进来 执行完毕才会退出的.


所以毕老师的这种方式 是不存在上面那种结果的
while(true){
     synchronized(this){
          if(tickt>0){

          }   
    }
}
作者: 袁錦泰    时间: 2012-5-19 12:46
贠(yun)靖 发表于 2012-5-19 12:17
是啊,如果是推出条件要写到while(tickt>0) 这样的话  synchronized必须写到while的外面才能保证同步
  ...

QQ号。                                          
作者: 贠(yun)靖    时间: 2012-5-19 12:57
袁錦泰 发表于 2012-5-19 12:46
QQ号。

273459401      
作者: 陈栋    时间: 2012-5-19 16:42
首先你这的问题是把所对象弄错了,你在run方法中定义了一个Object对象当成所对象是存在问题的,没启动一个线程的时候都会运行run方法,所以对于不同的线程来说Object都是不同的你使用synchrozied(obj)就起不到同步的作用,而毕老师使用的synchrozied(this)是使用对象本身作为同步锁,每个线程使用相同的对象生成是能够达到同步效果




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