黑马程序员技术交流社区

标题: 关于线程的问题 求解求解 [打印本页]

作者: che201311    时间: 2013-11-21 22:27
标题: 关于线程的问题 求解求解
public class Ticket {

public static void main(String[] args){

Loket l1 = new Loket(1);
Loket l2 = new Loket(2);
Loket l3 = new Loket(3);
Loket l4 = new Loket(4);
Loket l5 = new Loket(5);
Thread t1 = new Thread(l1);
Thread t2 = new Thread(l2);
Thread t3 = new Thread(l3);
Thread t4 = new Thread(l4);
Thread t5 = new Thread(l5);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}


}

class Loket implements Runnable{
static int ticketnum =100;
static int count = 0;
int a;
Loket(int a){
this.a = a;
}
public synchronized void run() {

while(ticketnum>0){       
System.out.println("第"+ a+"个售票窗口售出:" +"第"+(++count)+
"张票");
ticketnum --;

   
}

try{
            Thread.sleep(1);
           
        }catch(InterruptedException e){
                e.printStackTrace();
        }

}
}
我设的静态变量ticketnum是100可是最后怎么count会变成104呢,按说应该也是100啊,如果把while换成if就只出来5张票,如果把下面的Thread.sleep()放到while循环中为什么又不到100张了,就是在90多张的地方就停住了。还有加锁到底应该在什么地方加锁啊,我加的synchronized地方对不对啊?菜鸟求大神指导啊

作者: ″先森丶玹°    时间: 2013-11-21 22:47
你在while循环下面加上一句:
if(count<100)
就行了。
你count并未定义++的上限,所以会出现101 102....这种票。
作者: che201311    时间: 2013-11-21 22:55
是这个道理
作者: qw无语    时间: 2013-11-21 23:04
首先.你的synchronized在写run()上
如果成果,应该只有一个线程把所有票卖挖.
但是结果,所有线程都卖出票了,所以synchronize没有成功.
run()方法这样写:
        public void run() {

                while (ticketnum > 0) {
                        synchronized (Loket.class) {
                                if (ticketnum > 0) {
                                        System.out.println("第" + a + "个售票窗口售出:" + "第" + (++count)
                                                        + "张票");
                                        ticketnum--;
                                }
                        }
                }

                try {
                        Thread.sleep(1);

                } catch (InterruptedException e) {
                        e.printStackTrace();
                }

        }
在里面再判断一次是因为可能在
所有线程while (ticketnum > 0)在这判断完可能被抢去执行权.
在没有--之前都在锁前,所以再加次判断.
作者: 唐志海    时间: 2013-11-21 23:45
当多条语句在操做同一个现场的共享数据,一个线程对多条语句只执行了一部分,另外一线程参与
执行,造成共享数据的错误。
作者: freehiker    时间: 2013-11-21 23:50
  1. public class Ticket {

  2.         public static void main(String[] args) {
  3.                 // TODO Auto-generated method stub
  4.                 new Thread(new Window()).start();
  5.                 new Thread(new Window()).start();
  6.                 new Thread(new Window()).start();
  7.                 new Thread(new Window()).start();
  8.                 new Thread(new Window()).start();
  9.                 new Thread(new Window()).start();
  10.                 new Thread(new Window()).start();
  11.                 new Thread(new Window()).start();
  12.         }

  13. }

  14. class Window implements Runnable {
  15.         static int count = 1;
  16.         public void run(){
  17.                 while(count<=10){
  18.                         synchronized(Window.class){
  19.                                 if(count<=10){
  20.                                         System.out.println(Thread.currentThread().getName()+"卖出了第"+count+"张票");
  21.                                         count++;
  22.                                 }
  23.                         }       
  24.                 }
  25.         }
  26. }
复制代码

作者: smileven    时间: 2013-11-22 01:18
(1)为什么count变成104:
第一你的多线程操作同一份数据用的不是同一把锁,所以当一个线程进入同步代码块等待时,其他线程也可以进入同步代码块,会造成线程安全问题。
因为线程结束的控制条件是ticketnum=0;也就是说只有ticketnum>0的时候,t1,t2,t3,t4,t5才可以进入同步代码块。
所以你的锁应该在while( ticketnum > 0)里面。
如果你这样写:当一个线程进入同步代码块,刚好判断完ticketnum的值为1,此线程挂在这儿。
此时又有新的线程进入同步代码块,判断ticketnum == 1也进入了同步代码块。
这样就是多个线程卖最后一张票,但是只有一张票,所以会出现负数票,count也就大于100了。

(2)while换成if就出来5张票:
因为主线程把t1,t2,t3,t4,t5开启之后,它们各自都卖了一张票,然后t1,t2,t3,t4,t5线程都已经结束了。
因为没有循环去卖剩下的票,if()只是一次判断条件,每个线程都判断一次,然后结束了线程。

(3)Thread.sleep()放在while()中卖不到100张票:
这个你多试几次,其实不是卖不到100张。我试的结果是可以买到90多张,可以买到100张,也可以买到101张。
这都是线程安全出问题造成的。

解决办法:
(1)t1,t2,t3,t4,t5五个线程操作ticketnum这一份数据必须使用同一把锁。
(2)进入同步代码的条件应该放在锁的外面。
具体代码楼上写的很好了,参考一下~~














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