2

My first question, Thank for your help! I'm trying to print odd and even numbers 1~100 alternatively using two threads. Expected results:

    pool-1-thread-1=> 1
    pool-1-thread-2=> 2
    pool-1-thread-1=> 3
    pool-1-thread-2=> 4
    ......
    pool-1-thread-1=> 99
    pool-1-thread-2=> 100

I think i can use FairSync, but it can only guarantee that most of the print is correct. like this:

pool-1-thread-1=> 55
pool-1-thread-2=> 56
pool-1-thread-1=> 57
pool-1-thread-2=> 58   
pool-1-thread-2=> 59  //※error print※
pool-1-thread-1=> 60
pool-1-thread-2=> 61
pool-1-thread-1=> 62

I don't know why is the order lost in very few cases? You can criticize my code and my English. Here is my code:

private static final int COUNT = 100;

private static final int THREAD_COUNT = 2;

private static int curr = 1;

static ReentrantLock lock = new ReentrantLock(true);

static ExecutorService executorService = Executors.newCachedThreadPool();

public static void main(String[] args) {
    Runnable task = () -> {
        for (; ; ) {
            try {
                lock.lock();
                if (curr <= COUNT) {
                    System.out.println(Thread.currentThread().getName() + "=> " + curr++);
                } else {
                    System.exit(0);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    };
    for (int i = 0; i < THREAD_COUNT; i++) {
        executorService.execute(task);
    }
}
student
  • 127
  • 5
  • 5
    See the documentation: " Note however, that fairness of locks does not guarantee fairness of thread scheduling. Thus, one of many threads using a fair lock may obtain it multiple times in succession while other active threads are not progressing and not currently holding the lock. " https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/locks/ReentrantLock.html – Erwin Bolwidt Sep 10 '19 at 03:35

2 Answers2

0

No dear your implementation is not correct. Which thread get's the opportunity to RUN is decided by the OS. Thread 1 & 2 will execute one after another cannot be guaranteed.

You can fix your code by checking the previous value of the variable curr and if the value is not what this thread expects don't increment and print.

for eg :

if(curr.threadName.equals("Thread 2") && (curr%2 !=0))
{
// Print
// Increment
}
Geek
  • 23,089
  • 20
  • 71
  • 85
0

You cant use single lock to achieve this. Even ReentrantLock gives fairness but it cant control thread schedule.

We can achieve throw inter thread communication like Semaphore. Semaphore controls the thread execution.

We create two threads, an odd thread, and an even thread. The odd thread would print the odd numbers starting from 1, and the even thread will print the even numbers starting from 2.

Create two semaphores, semOdd and semEven which will have 1 and 0 permits to start with. This will ensure that odd number gets printed first.

class SharedPrinter {

    private Semaphore semEven = new Semaphore(0);
    private Semaphore semOdd = new Semaphore(1);

    void printEvenNum(int num) {
        try {
            semEven.acquire();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        System.out.println(Thread.currentThread().getName() + num);
        semOdd.release();
    }

    void printOddNum(int num) {
        try {
            semOdd.acquire();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        System.out.println(Thread.currentThread().getName() + num);
        semEven.release();

    }
}

class Even implements Runnable {
    private SharedPrinter sp;
    private int max;

    // standard constructor

    @Override
    public void run() {
        for (int i = 2; i <= max; i = i + 2) {
            sp.printEvenNum(i);
        }
    }
}

class Odd implements Runnable {
    private SharedPrinter sp;
    private int max;

    // standard constructors 
    @Override
    public void run() {
        for (int i = 1; i <= max; i = i + 2) {
            sp.printOddNum(i);
        }
    }
}

public static void main(String[] args) {
    SharedPrinter sp = new SharedPrinter();
    Thread odd = new Thread(new Odd(sp, 10),"Odd");
    Thread even = new Thread(new Even(sp, 10),"Even");
    odd.start();
    even.start();
}

Refer : here

Siva Kumar
  • 1,983
  • 3
  • 14
  • 26
  • You could use a single `Lock` for this using two `Condition` objects. One could probably come up with a single `Condition` implementation as well. – Slaw Sep 10 '19 at 05:15