java多线程实在弄不懂

新手上路,请多包涵

源码如下:
package com.study.test;

/*实现Runnable对象实现多线程
* @author who
* @since 2015-05-05
* */

/*用多线程实现卖票功能
* 一共1000张票,每卖一张票-1
* */
class Ticket implements Runnable {
private int tick = 1000;
boolean bb = true;
public void run() {
// TODO Auto-generated method stub
if (bb) {
while (true) {
if (tick > 0) {
synchronized (this) {
try {
System.out.println("当前boolean值来自run方法:" + bb);
Thread.sleep(20);
System.out.println(Thread.currentThread().getName()
+ "...sale " + tick--);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
} else {
while (true)
SaleTicket();
}
}

public synchronized void SaleTicket() {
    if (tick > 0) {
        try {
            System.out.println("当前boolean值来自SaleTicket方法:" + bb);
            Thread.sleep(20);
            System.out.println(Thread.currentThread().getName()
                    + "...SaleTicket " + tick--);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

}

class TicketDemo {

public static void main(String[] args) {
    // TODO Auto-generated method stub
    Ticket t = new Ticket();
    Thread t1 = new Thread(t, "线程1:");
    Thread t2 = new Thread(t, "线程2:");
    Thread t3 = new Thread(t, "线程3:");
    Thread t4 = new Thread(t, "线程4:");
    t1.start();
    Sleep20();
    t.bb = false;
    t2.start();
    Sleep20();
    t.bb = true;
    t3.start();
    Sleep20();
    t.bb = false;
    t4.start();
}

public static void Sleep20() {
    try {
        Thread.sleep(20);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

}

部分执行输出如下:
当前boolean值来自run方法:true
线程1:...sale 1000
当前boolean值来自run方法:false
线程1:...sale 999
当前boolean值来自SaleTicket方法:true
线程2:...SaleTicket 998
……………………………………
当前boolean值来自run方法:false
线程1:...sale 2
当前boolean值来自run方法:false
线程1:...sale 1
当前boolean值来自run方法:false
线程3:...sale 0
疑问如下:
1、根据代码得知,当bb变量为true时才会进入run方法的同步代码块,否则会进入SaleTicket同步方法中,但是以上输出当前boolean值完全是乱的。
2、针对两个同步代码块都做了同步安全处理,尽然还有“0”值出现,在开启两个线程的情况下不会出现。

阅读 3k
1 个回答

run()中,先判断bb值,再进入同步代码段,导致可能出现这种情况:bb值为true, 进入同步代码段前,另一线程修改bb的值为false。同理,synchronized也没有把tick作为临界区保护起来。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题