首页 > 解决方案 > Alternating Output Number and Letter in 2 Threads without Lock

问题描述

In an interview I was asked to use 2 and only 2 threads to print the string 1A2B3C...24X25Y26Z, where one thread only prints numbers and the other only prints letter. I wrote the following code:

public class App {
    static volatile int x = 0;
    static volatile boolean numPrinted = false;

    static class NumThread implements Runnable {
        @Override
        public void run() {
            while (x < 26) {
                if (!numPrinted) {
                    System.out.print(x + 1);
                    numPrinted = true;
                }
            }
        }
    }

    static class LetterThread implements Runnable {
        @Override
        public void run() {
            while (x < 26) {
                if (numPrinted) {
                    System.out.print((char) ('A' + x));
                    ++x;
                    numPrinted = false;
                }
            }
        }
    }


    public static void main(String[] args) {
        Thread foo = new Thread(new NumThread());
        Thread bar = new Thread(new LetterThread());
        foo.start();
        bar.start();
        try {
            foo.join();
            bar.join();
        } catch (InterruptedException ignored) {

        }
        System.out.println();
    }
}

In about 1 out of 10 runs, it will produce

1A2B3C4D5E6F7G8H9I10J11K12L13M14N15O16P17Q18R19S20T21U22V23W24X25Y26Z27

What's the concurrency issue with my code? I avoid AtomicInteger intentionally.

标签: javamultithreadingconcurrency

解决方案


Both threads are busy-waiting. So this is possible:

  • LetterThread prints Z
  • NumThread checks if x<26, it is
  • LetterThread increments x, sets numPrinted=false
  • NumThread check numPrinted, it is false, so prints 27

In NumThred check x again after numPrinted.


推荐阅读