java 相同线程重锁重入锁

gc0ot86w  于 2023-01-04  发布在  Java
关注(0)|答案(2)|浏览(144)

我写了一段代码,它应该使用运行在不同线程上的两种不同方法来打印“乒乓”。
共享工作代码:

package threading;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class PingPong {

  private static volatile int times;
  private static volatile boolean ping;
  private static final Lock lock = new ReentrantLock();

  private static void ping() {
    int i = 1;
    while (i < times) {
        lock.lock();

        if (ping) {
          System.out.print("ping ");
          ping = !ping;
          i += 1;
        }

        lock.unlock();
    }
  }

  private static void pong() {
    int i = 1;
    while (i < times) {
        lock.lock();

        if (!ping) {
          System.out.println("pong");
          ping = !ping;
          i += 1;
        }

        lock.unlock();
    }
  }

  public static void main(String[] args) {
    times = 10;
    ping =true;

    Thread pingThread = new Thread(PingPong::ping);
    Thread pongThread = new Thread(PingPong::pong);

    pingThread.start();
    pongThread.start();
  }
}

本例中的输出:

ping pong
ping pong
ping pong
ping pong
ping pong
ping pong
ping pong
ping pong
ping pong

如果我用for循环替换ping和pong方法中的while循环,同一个线程似乎一次又一次地锁定,不给第二个线程公平的机会进入。这种情况下的输出是不一致的,每次都出现不同的结果。while循环执行的事情是否不同,从而给第二个线程获得锁的机会?

oxcyiej7

oxcyiej71#

我看不出"for"和"while"之间有什么特别的区别,但是你编写的代码,即使有"while",也不能保证你想要的行为。
ReentrantLock documentation
此类的构造函数接受一个可选的公平参数。当设置为true时,在争用情况下,锁优先将访问权授予等待时间最长的线程。否则,此锁不保证任何特定的访问顺序。
你应该使用一个"公平"的锁来避免一个线程挨饿。即使这样,也不能保证当一个线程拥有锁时,另一个线程会调用它自己的lock(),以确保它在unlock()执行后立即成为下一个线程。

wkftcu5l

wkftcu5l2#

您可以在每个循环之间使用延迟或使用其他方法来控制线程。

while staus != finish {
  if status = ping {
    lock.lock();
    System.out.println("ping");
    ping = pong;
    lock.unlock();
  }
  # A delay here avoids 100% active CPU
}

相关问题