java - 如何正确同步两个线程

标签 java multithreading synchronization semaphore

这是一个我在学校一直听说的问题,但在我被要求面试之前从来没有理由去解决。

提示:使用 2 个线程按顺序打印 "Thread i: The number is 'j'" 其中 j = 1:100,i 是线程号。线程 1 只能打印奇数 j,线程 2 只能打印偶数 j。

编辑 j 的输出必须排序

这是我的尝试,但我没有在面试过程中继续前进。我缺少任何基本部分吗?有什么优化吗?

import java.util.concurrent.Semaphore;

public class ThreadSynchronization implements Runnable {

  private int start;
  private Semaphore semaphore;

  private ThreadSynchronization(int start, Semaphore semaphore) {
      this.start = start;
      this.semaphore = semaphore;
  }

  public static void main(String[] args) {
      Semaphore semaphore = new Semaphore(1, true);
      semaphore.acquireUninterruptibly();

      start(1, semaphore);
      start(2, semaphore);

      semaphore.release();
  }

  private static void start(int start, Semaphore semaphore) {
      ThreadSynchronization ts = new ThreadSynchronization(start, semaphore);
      Thread thread = new Thread(ts);
      thread.start();
      while (thread.getState() != Thread.State.WAITING) ;
  }

  @Override
  public void run() {
      for (int i = start; i <= 100; i += 2) {
          semaphore.acquireUninterruptibly();
          System.out.println("Thread " + start + ": The number is '" + i + "'");
          semaphore.release();
      }
  }
}

最佳答案

一个线程可以不断获取和释放Semaphore,而另一个线程处于饥饿状态。

你可以用 waitnotify 来做到这一点,试试这个:

import java.util.concurrent.atomic.AtomicInteger;

class Odd implements Runnable {

    private AtomicInteger integer;
    private final Object lock;

    public Odd(AtomicInteger integer, Object lock) {
        this.integer = integer;
        this.lock = lock;
    }

    @Override
    public void run() {
        synchronized (lock) {
            try {
                while (integer.get() <= 100) {
                    while (integer.get() % 2 == 0) {
                        lock.notify();
                        lock.wait();
                    }
                    if (integer.get() <= 100) {
                        System.out.println("Thread " +
                                Thread.currentThread().getName() + ": The number is '" + integer.get() + "'");
                    }
                    integer.getAndIncrement();
                    lock.notify();
                }
            } catch (Exception e) {

            }
        }
    }
}

class Even implements Runnable {

    private AtomicInteger integer;
    private final Object lock;

    public Even(AtomicInteger integer, Object lock) {
        this.integer = integer;
        this.lock = lock;
    }

    @Override
    public void run() {
        synchronized (lock) {
            try {
                while (integer.get() <= 100) {
                    while (integer.get() % 2 != 0) {
                        lock.notify();
                        lock.wait();
                    }
                    if (integer.get() <= 100) {
                        System.out.println("Thread " +
                                Thread.currentThread().getName() + ": The number is '" + integer.get() + "'");
                    }

                    integer.getAndIncrement();
                    lock.notify();
                }
            } catch (Exception e) {

            }
        }
    }
}

public class ThreadSynchronization {

    public static void main(String[] args) throws Exception{
        Object lock = new Object();
        AtomicInteger integer = new AtomicInteger(1);
        Odd odd = new Odd(integer, lock);
        Even even = new Even(integer, lock);

        Thread thread1 = new Thread(odd, "1");
        Thread thread2 = new Thread(even, "2");

        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();
    }

}

关于java - 如何正确同步两个线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54140289/

相关文章:

java - JPA中最大打开游标数超出异常(使用createNativeQuery删除记录)

java - 多少类太多了?什么时候适合添加新类?

java - Andengine 将位图附加到场景

c# - c# 中正确的队列线程技术?

c++ - 使用 CriticalSection 创建类似互斥锁的程序

java - Java线程不会同步

synchronization - p4sync -f 不覆盖打开的文件

java - "Illegal Class Literal"是什么意思?

Java EE6 优于 EE5?

Ruby 多线程/多处理读物