1

チケットを販売するためのグローバル変数がある単純な問題を実装しようとしています。10 枚のチケットを販売するために 3 つのスレッドを生成します。これは、バイナリ セマフォを使用して行っています。

private static int noOfTickets =10;
private static boolean soldAll = false;
private static Random r = new Random(10);

/************ MAIN **************/
public static void main(String[] arg){
    // spawn 10 threads to see a tickets

    for(int i =0; i<3; i++){
        Thread t = new Thread(new sellRunnable());
        t.setName("Me_"+i);
        t.start();
    }
}
/************ MAIN **************/


public static void sell() throws InterruptedException{
    Semaphore b = new Semaphore(1);
    int numOfTicketsSoldByThisThread = 0;
    while(!soldAll){

        addRandomDelay(1000, 100);

        b.acquire();
        if(noOfTickets>0){
            Thread t = Thread.currentThread();
            numOfTicketsSoldByThisThread++;
            noOfTickets--;
            System.out.println("I "+t.getName()+" sold "+numOfTicketsSoldByThisThread+"ticket. tickets left are "+noOfTickets);


        }else{
            soldAll = true;
            System.out.println(" sold all tickets");
        }
        b.release();
    }// end of while


}

public static class sellRunnable implements Runnable{

    public void run() {
        try {
            sell();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

}

このコードを実行すると、正しい出力が得られません。ある時点でこれが得られます

  • I Me_2 は 1 チケットを売りました。チケットは残り7枚
  • I Me_1 は 1 チケットを売りました。チケットは残り7枚

残りのチケットが 7 であることを 2 つのスレッドが出力していることに注意してください。それは正しくありませんか?noOfTicketsLeft-- はアトミック操作ではなく、セマフォ内にあることはわかっています。それで、それはうまくいくはずですか?

4

1 に答える 1

1

3 つのスレッドすべてに同じ Semaphore インスタンスを使用する必要があります。現状では、それらはすべて異なるセマフォを指しているため、実際にはお互いをロックアウトしていません。

ところで、これは簡単な練習用に見えるかもしれませんが、静的変数を使用する習慣から抜け出す必要があります。クラスを宣言し、それをインスタンス化し、main() で呼び出します。それ以上の手間はかからず、はるかにクリーンです。

于 2013-07-27T01:08:26.063 に答える