Java中的线程之间的通信没有锁定

时间:2015-05-30 01:25:31

标签: java multithreading conditional-statements reentrantlock

所以我想要实现的是两个线程轮流执行他们的任务。我原来只有一个问题;

  1. 如何在不使用锁的情况下实现两个线程轮流执行任务?我不想要锁的原因是因为我感觉很愚蠢,当没有两个线程试图访问的公共资源时使用锁。
  2. 所以我打算做一个代码的小例子,然后我发现即使有锁,我也无法使它工作。所以我的第二个问题是;我如何使代码按预期工作?我看到它的方式,它应该工作,但那只是我:)。

    1. Thread1打印消息
    2. Thread1表示Thread2可以打印消息
    3. Thread2打印消息
    4. Thread2表示Thread1可以从头开始
    5. public class App {
      
          Lock lock = new ReentrantLock();
          Condition cond1 = lock.newCondition();
          Condition cond2 = lock.newCondition();
      
          public App() {
              Thread thread1 = new Thread(new Runnable() {
                  @Override
                  public void run() {
                      try {
                          while (true) {
                              lock.lock();
                              System.out.println("Thread 1");
                              cond2.signalAll();
                              cond1.await();
                              lock.unlock();
                          }
                      } catch (InterruptedException e) {
                      }
                  }
              });
              thread1.start();
      
              Thread thread2 = new Thread(new Runnable() {
                  @Override
                  public void run() {
                      try {
                          while (true) {
                              lock.lock();
                              cond2.await();
                              System.out.println("           Thread 2");
                              cond1.signalAll();
                              lock.unlock();
                          }
                      } catch (InterruptedException e) {
                      }
                  }
              });
              thread2.start();
          }
      
          public static void main(String[] args) {
              new App();
          }
      
      }
      

2 个答案:

答案 0 :(得分:2)

(1)await()通常用于循环中;不这样做是一个错误的迹象。

while( some condition not met )
    cond.await();

(2)unlock()应位于finally

(3)signal()仅表示当前正在等待的线程;如果没有线程等待,信号就会丢失。

    lock.lock();
    cond.signal(); // lost
    cond.await();  // won't wake up

(4)对于像这样的简单案例,使用好的旧synchronized没有错。实际上,在使用更多" advanced"之前,你最好先理解它。东西。

(5)解决方案:

    Lock lock = new ReentrantLock();
    Condition cond = lock.newCondition();
    int turn=1; // 1 or 2


    // thread1

            lock.lock();
            try
            {
                while (true)
                {
                    while(turn!=1)
                        cond.await();
                    System.out.println("Thread 1");
                    turn=2;
                    cond.signal();
                }
            }
            finally
            {
                lock.unlock();
            }

    // thread2
    // switch `1` and `2`

(6)一个线程环,每个都唤醒下一个

    int N = 9;
    Thread[] ring = new Thread[N];
    for(int i=0; i<N; i++)
    {
        final int ii = i+1;
        ring[i] = new Thread(()->
        {
            while(true)
            {
                LockSupport.park();   // suspend this thread
                System.out.printf("%"+ii+"d%n", ii);
                LockSupport.unpark(ring[ii%N]);  // wake up next thread
                // bug: spurious wakeup not handled 
            }
        });
    }

    for(Thread thread : ring)
        thread.start();

    LockSupport.unpark(ring[0]);  // wake up 1st thread

答案 1 :(得分:0)

您可以使用thread notify()和wait():Oracle Documentation