FairSync可以保证执行顺序吗?

时间:2019-09-10 03:24:04

标签: java multithreading reentrantlock

我的第一个问题,谢谢您的帮助! 我正在尝试使用两个线程来打印奇数和偶数1〜100。 预期结果:

    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

我认为我可以使用FairSync,但只能保证大多数打印正确。像这样:

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

我不知道为什么在极少数情况下会丢失订单? 您可以批评我的代码和我的英语。 这是我的代码:

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);
    }
}

2 个答案:

答案 0 :(得分:0)

亲爱的,您的实现不正确。哪个线程获得运行的机会由操作系统决定。线程1和2将无法保证一个接一个地执行。

您可以通过检查变量curr的前一个值来修复代码,如果该值不是该线程期望的值,则不要递增和打印。

例如:

if(curr.threadName.equals("Thread 2") && (curr%2 !=0))
{
// Print
// Increment
}

答案 1 :(得分:0)

您不能使用单锁来实现此目的。甚至ReentrantLock都公平,但它无法控制线程调度。

我们可以实现诸如Semaphore之类的抛出线程间通信。信号量控制线程的执行。

我们创建两个线程,一个奇数线程和一个偶数线程。奇数线程将打印从1开始的奇数,偶数线程将打印从2开始的偶数。

创建两个信号量semOdd和semEven,它们的起始编号为1和0。这样可以确保先打印奇数。

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();
}

引用:here

相关问题