关于多线程的一个问题

choaklin 发布于 2014/09/15 21:45
阅读 153
收藏 1

关于多线程的一个问题,望得到解惑

代码如下

package thread.extend;

/**
 * created by choaklin on 14-9-15.
 */
public class SellTicket {

    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        Thread t1 = new Thread(ticket, "售票窗口1");
        Thread t2 = new Thread(ticket, "售票窗口2");
        Thread t3 = new Thread(ticket, "售票窗口3");

        t1.start();
        t2.start();
        t3.start();
    }
}

class Ticket extends Thread {
    private int ticket = 20;

    public void run() {
        while (true) {
            if (ticket > 0) {
                System.out.println(Thread.currentThread().getName() + " 出售票号: " + (ticket--));
            } else {
                break;
            }
        }
    }
}



运行结果:出现2个20

售票窗口2 出售票号: 20
售票窗口2 出售票号: 18
售票窗口2 出售票号: 17
售票窗口2 出售票号: 16
售票窗口2 出售票号: 15
售票窗口2 出售票号: 14
售票窗口2 出售票号: 13
售票窗口2 出售票号: 12
售票窗口2 出售票号: 11
售票窗口2 出售票号: 10
售票窗口2 出售票号: 9
售票窗口3 出售票号: 19
售票窗口3 出售票号: 7
售票窗口1 出售票号: 20
售票窗口3 出售票号: 6
售票窗口3 出售票号: 4
售票窗口2 出售票号: 8
售票窗口3 出售票号: 3
售票窗口1 出售票号: 5
售票窗口3 出售票号: 1
售票窗口2 出售票号: 2



这个是多次运行才有概率出现的问题,在此有此疑惑:

1、3个线程共享一个target,为什么会出现这个问题?

2、变量打印是无序的,如何使得可以连续的打印

希望可以得到一些理论


加载中
0
DavidWTF
DavidWTF

嗯,应该有3个20,不知道是否你没贴全。你的ticket是每个线程有一个的,不是共享的。

除非你用同步机制,不然肯定是无序的。

choaklin
choaklin
运行没有出现22条记录过...
0
quanwei9958
quanwei9958

你现在是每个线程一个ticket,如果想共享,给ticket加上static属性

为了保证打印的顺序,完整,要加上一个共享锁,也即

public void run() {
        while (true) {
          synchronized(static_lock){
            if (ticket > 0) {
                System.out.println(Thread.currentThread().getName() + " 出售票号: " + (ticket--));
            } else {
                break;
            }
          }
        }
    }



其中的static_lock也是一个static对象就行了

省事点就用刚刚的那个static的ticket当static_lock了

synchronized(ticket)

{

        ...

}

quanwei9958
quanwei9958
回复 @choaklin : 你这个和Thead thrad1=Ticket();是一样的,他通过ticket创建了三个对象。对你这个程序而言你这里的Ticket extends Thread相当与Ticket extends Runable了,当成一个接口用了
choaklin
choaklin
如果每个线程独立一个ticket,不是应该这样创建线程吗? Thread t1 = new Thread("售票窗口1"); Thread t2 = new Thread("售票窗口2"); Thread t3 = new Thread("售票窗口3");
0
pczhangtl
pczhangtl

1. ticket不是线程安全的,所以会打印出来多个20.

2. 可以考虑使用synchronized, notify和wait来实现。

0
limaofeng
limaofeng
原因就是ticket--不是原子操作。多线程时出现了并发
返回顶部
顶部