A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 庄星睿 中级黑马   /  2012-6-5 12:11  /  3300 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 庄星睿 于 2012-6-5 12:16 编辑

今天复习同步锁时又遇到一个状况:
  1. class Ticket implements Runnable
  2. {
  3.       private int tick=100;
  4.       Object obj=new Object();
  5.       public void run()
  6.      {
  7.          while (true)
  8.         {
  9.             synchronized (new Object())  //这里把obj换成new Object()
  10.            {
  11.                  if (tick>0)
  12.                 {
  13.                       try{Thread.sleep(10);}catch (Exception e){}
  14.                       System.out.println(Thread.currentThread().getName()+"...."+"tick:.."+tick--);
  15.                 }
  16.             }

  17.        }

  18.    }
  19. }
复制代码
  1. class TicketDemo
  2. {
  3.      public static void main(String[] args)
  4.    {
  5.          Ticket t=new Ticket();
  6.          Thread t1=new Thread(t);
  7.          Thread t2=new Thread(t);
  8.          Thread t3=new Thread(t);
  9.          Thread t4=new Thread(t);
  10.          t1.start();
  11.         t2.start();
  12.         t3.start();
  13.         t4.start();
  14.    }
  15. }
复制代码
运行结果:
Thread-1....tick:..6
Thread-2....tick:..5
Thread-2....tick:..4
Thread-1....tick:..2
Thread-3....tick:..3
Thread-0....tick:..1
Thread-1....tick:..0
Thread-2....tick:..-2
Thread-3....tick:..-1

Object obj=new  Object()
synchronized(obj)
运行结果:
Thread-2....tick:..6
Thread-2....tick:..5
Thread-2....tick:..4
Thread-2....tick:..3
Thread-2....tick:..2
Thread-2....tick:..1

运行结果就不会出现异常  -1,-2 ,我传obj 和new Object()不都是Object的对象吗,为什么结果却不一样呢?

6 个回复

倒序浏览
Object obj=new Object(); 所创建的对象是成员变量,一旦Ticket的对象被创建,就存在于对象的方法区中。每个线程到 synchronized (obj) 进行判断时,使用的锁是同一个。但是synchronized (new Object())中创建的对象时临时的,每运行一次,创建一个,马上又释放了。所以每个线程到此处所使用的锁是不断变化的,所以,无法实现同步吧。
回复 使用道具 举报
使用new Object()作为锁的话,对象的建立是临时的,每次运行,都要创建,导致使用同步代码块的锁失去了唯一性,多线程就会出现安全问题。
回复 使用道具 举报
同步锁,要同一把锁! new Object()  每次都是新的对象 不是同一个对象!
回复 使用道具 举报
这里面其实就是线程的一些需要注意的问题,
一是线程的开启方式:调用start()方法;
二是线程默认执行的程序是在 run()中的内容,即一个线程开启就会执行;
三是同步问题: 首先要先定义同样的锁,很明显如果是在run()方法中 定义synchronized (new Object()),当每个线程开启时,对于每个线程来说都是一个新的锁,而不是   一 个统一的锁是吧。 然后如果是在run()外面就先定义一个锁,然后在 synchronized (object)调用时,就是统一的一个锁了。

其实就是同步的问题和对锁的定义问题了。

回复 使用道具 举报
     1、为什么会出现负数:
      是因为,当某个线程在睡觉10秒的过程中,变量ticket的值是1,还没有输出和做减去1之前,这个ticket等于1,仍然大于0;然后下一个线程运行,ticket仍然是1,然后输出后自减,所以ticket为0了,此时,睡觉的线程醒来了,输出ticket的自减,即0-1,所以有了负数。原因就是变量ticket是各个线程共享的数据。
  2、关于对象锁。
你用的new Object(),这是新创建了一个对象,不是同一把锁。用同一把锁就能解决线程安全问题
回复 使用道具 举报
焦健 高级黑马 2013-2-25 21:22:24
7#
学习了。。。。。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马