1

I run the main method after a while, it will always print nothing.

But if I uncomment "System.out.println(111);" and "System.out.println(222);",it will run normal i think.

I fetch the dump of 'soldWorker' thread and 'refundWorker' thread, they stop at the if judge.

public class ProducerAndConsumer2 {

    public static void main(String[] args) {
        SyncTikcet2 syncTikcet = new SyncTikcet2(1);

        Runnable syncSoldTicket = () -> syncTikcet.soldTicket();
        Runnable syncRefundTicket = () -> syncTikcet.refund();

        new Thread(syncSoldTicket, "soldWorker").start();
        new Thread(syncRefundTicket, "refundWorker").start();
    }
 }

class SyncTikcet2 {

    private Integer ticketNum;

    public SyncTikcet2(Integer ticketNum) {
        this.ticketNum = ticketNum;
    }


    public void soldTicket() {
        while (true) {
            if (ticketNum > 0) {
                ticketNum = ticketNum - 1;
                System.out.println("sold ticket,the num is" + ticketNum);
            } else {
                // System.out.println(111);
            }
        }
    }

    public void refund() {
        while (true) {
            if (ticketNum == 0) {
                ticketNum = ticketNum + 1;
                System.out.println("refund ticket,the num is" + ticketNum);
            } else  {
                // System.out.println(222);
            }
        }
    }

    public Integer getTicketNum() {
        return ticketNum;
    }

    public void setTicketNum(Integer ticketNum) {
        this.ticketNum = ticketNum;
    }
}

1 Answers1

3

If you haven't made the field volatile, there is no reason for a thread to re-read a value it didn't change.

Try using private volatile int ticketNum

I suggest using a primitive e.g. int, unless you have to use an Object reference. It's not only faster but it also makes it clear you don't expect the value to be null.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • thank you very much, you are so great, your answer guide me to find another question [link](https://stackoverflow.com/questions/25425130/loop-doesnt-see-changed-value-without-a-print-statement). This question is the same as mine and it's answer more detailed. Thank you very much once again. – wr1ttenyu zhao Nov 14 '18 at 09:05
  • 1
    @wr1ttenyuzhao note System.out.println has a `synchronized` memory barrier, however if it's not called you might not see an update. – Peter Lawrey Nov 14 '18 at 09:14
  • yeah, this is why it will run normal when i uncomment "System.out.println(111);" and "System.out.println(222);", thank your answer, you are a good man, thanks – wr1ttenyu zhao Nov 14 '18 at 09:59