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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 小悠久 中级黑马   /  2014-1-15 16:09  /  1216 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 小悠久 于 2014-1-15 20:50 编辑

关于售票这个问题,我用继承Tread方法,在毕老师是将票数直接在输出里tick--,我将它放到下边为什么就不行啦,是多线程安全的问题吗?那为什么加入同步代码块也不行?麻烦各位帮忙看下,谢谢啦
public class threadTest {
/**
  * @param args
  */
public static void main(String[] args) {
  // TODO Auto-generated method stub
        c t0= new c();
        c t1= new c();
        c t2= new c();
        t0.start();
        t1.start();
        t2.start();
}
}
class c extends Thread
{
private static int count=100;
public void run()
{
  while(true){
   synchronized (this) {
    if(count>0)
    {
     System.out.println(Thread.currentThread().getName()+":"+count);
     count--;      //我将递减放到下面为什么会出现重复的数,如果是多线程安全问题,为什么同步代码块也不行
    }
    else{
      return;
     }
   }
   
   }
   
  }
}

5 个回复

倒序浏览
你确定毕老师是这么教你同步的么?
回复 使用道具 举报
aaaaaaaaaaaaaaaaaaaaaaaa
回复 使用道具 举报
很明显你的锁对象this 是 c0 c1 c2 根本就不相同,所以根本就没有同步
回复 使用道具 举报
  1. public class ThreadTest {
  2.         /**
  3.          * @param args
  4.          */
  5.         public static void main(String[] args) {
  6.                 // TODO Auto-generated method stub
  7.                 c cc = new c();
  8.                 Thread t0 = new Thread(cc);
  9.                 Thread t1 = new Thread(cc);
  10.                 Thread t2 = new Thread(cc);
  11.                 t0.start();
  12.                 t1.start();
  13.                 t2.start();
  14.         }
  15. }

  16. class c implements Runnable {
  17.         private static int count = 1000;

  18.         public void run() {
  19.                 while (true) {
  20.                         synchronized (this) {
  21.                                 if (count > 0) {
  22.                                         System.out.println(Thread.currentThread().getName() + ":"
  23.                                                         + count);
  24.                                 } else {
  25.                                         return;
  26.                                 }
  27.                                 count--; // 我将递减放到下面为什么会出现重复的数,如果是多线程安全问题,为什么同步代码块也不行
  28.                         }

  29.                 }

  30.         }
  31. }
复制代码


  1. public class ThreadTest {
  2.         /**
  3.          * @param args
  4.          */
  5.         public static void main(String[] args) {
  6.                 // TODO Auto-generated method stub
  7.                 c t0 = new c();
  8.                 c t1 = new c();
  9.                 c t2 = new c();
  10.                 t0.start();
  11.                 t1.start();
  12.                 t2.start();
  13.         }
  14. }

  15. class c extends Thread {
  16.         private static int count = 1000;

  17.         public void run() {
  18.                 while (true) {
  19.                         synchronized (c.class) {
  20.                                 if (count > 0) {
  21.                                         System.out.println(Thread.currentThread().getName() + ":"
  22.                                                         + count);
  23.                                 } else {
  24.                                         return;
  25.                                 }
  26.                                 count--; // 我将递减放到下面为什么会出现重复的数,如果是多线程安全问题,为什么同步代码块也不行
  27.                         }

  28.                 }

  29.         }
  30. }
复制代码


上面是两种同步执行的方法
第一种是c这个类 去实现Runable接口,此时使用new Thread去创建一个线程,并将c的对象cc作为每个线程的执行对象,因为三个线程使用的是同一个对象,也就是所synchronized是使用同一把锁,所以可以实现同步

第二种方法是继承Thread类  这时如果要开启多个线程可能就需要去new多个c的对象了,如果是多个对象,使用synchronized(this)肯定是不行的,this表示的是当前类的对象,new了3个对象就是开辟了3块内存,自己使用自己的锁何谈同步呢!所以要使用c.class 使用类的字节码作为同步锁,因为类是唯一的,而对象是可以有多个的。


你自己的方法你可以多执行几次,可以发现即便是count--在你现在写的位置也是会出现重复数据的,因为你就是new了多个对象,而让你看起来貌似正确的原因就是你的count定义为static,定义为静态之后count这个变量就是一个全局变量了,也就是说每个操作都会影响其值。

不知道能不能理解,欢迎留言讨论。  
上个回复没写完,一着急发了一堆乱七八糟的东西  见谅。
回复 使用道具 举报
强子 发表于 2014-1-15 17:22
上面是两种同步执行的方法
第一种是c这个类 去实现Runable接口,此时使用new Thread去创建一个线程, ...

非常感谢,已经明白啦
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马