【问题标题】:Convert wait & notifyAll code to use Java 1.5 Lock object将 wait 和 notifyAll 代码转换为使用 Java 1.5 Lock 对象
【发布时间】:2011-08-18 00:58:57
【问题描述】:

我们使用在代码段周围使用同步块的代码,其中包含大量等待和 notifyAll() 调用。我们正在尝试将它们转换为使用 Java 5 Lock.lock() 和 Lock.unlock() 方法。如何迁移此代码以删除所有 wait 和 notifyAll 调用。我不知道这些使用新的锁定功能的等价物。

任何带有示例的链接将不胜感激。

提前致谢

等式,下面的代码需要转换为使用Lock.lock()和lock.unlock 删除同步块的第一部分很简单,我只需要调用lock()方法。问题是 notifyAll() 和 wait 方法可以做什么。

同步(锁定) { 而(!Thread.interrupted()) { 尝试 { 工作=运行规则(); 如果(!工作) LOCK.notifyAll(); LOCK.wait(工作?shortTimeout:longTimeout); } 捕获(最终中断异常 e) { Package.log.info("线程被中断。退出。", e); 返回; } } }

【问题讨论】:

  • 如果您可以发布代码示例,您将获得更好的结果——1.5 中有许多并发原语。在示例之外给你建议可能会给你错误的答案。
  • 感谢您的回复。我已经添加了您要求的代码 sn-p。
  • ReentrantLocks 比 synchronized 块更容易出错 - 很容易错过 finally 块。因此,除非您需要某些特定功能 - lockInterruptibly 或 tryLock - 否则转换代码是没有意义的。如果您决定将代码迁移到更新的 API,则应考虑重构代码以使用更高级别的 API,例如 Semaphores、Latches 或 Barriers。
  • @Binil - 除了您对 Semaphore 的引用之外,我同意一切。我会认为 Semaphore 与 Lock 和 wait/notify 的 API“级别”相同。

标签: java multithreading concurrency thread-safety


【解决方案1】:

使用Conditions provided by the java.util.concurrent.locks package:

 final Object monitor = ...

 ...

 synchronized (monitor) {

     while (!condition) monitor.wait();
     ... do something ...
 }

变成:

 final ReentrantLock lock = ...;
 final Condition cvar = lock.newCondition();

 ...

 lock.lock();

 try {

     while (!condition) cvar.await();
     ... do something ... 

 } finally {

     lock.unlock();
 }

信号方面非常相似:

 synchronized (monitor) {

      ... do something ...
      monitor.notify();
 }

变成:

 lock.lock();

 try {

     ... do something ...
     cvar.signalAll();

 } finally {

     lock.unlock();
 }

【讨论】:

  • 感谢您的回复。我试试这个
【解决方案2】:

使用Lock.newCondition() 工厂方法提供的Condition 对象。对象监视器的等待和通知方面已被考虑到此接口中。

从迁移的角度来看:

  • wait() -> await()
  • wait(long) -> await(long, TimeUnit.Millis) 或 awaitNanos(long * 10000000)
  • notify() -> signal()
  • notifyAll() -> signalAll()

但是,条件在某些方面比监视器更强大。首先,它们的粒度更细,因此您可以为不同的事物设置多个条件。例如,如果我有一个有界阻塞集合,我可以有一个完整的条件和一个空的条件,并在添加或删除元素时分别等待和通知它们。

还有额外的await 变体允许您在不被中断的情况下等待并等待到某个特定日期(时间)。

Condition 类的 javadocs 非常好,非常详细地描述了它及其用途。

【讨论】:

    【解决方案3】:

    由于这个问题是关于 notifyAll,我尝试了一些带有移相器的生产者/消费者示例。我没有使用Lock,因为它需要try/finally,条件对象,直到解锁其他线程将无法工作......等等......

    import java.util.concurrent.Phaser;
    
    public class ProducerConsumerExample {
    
        Phaser producer;
        Phaser consumers;
        volatile String array[];
    
        public void init() {
            producer = new Phaser(5);
            consumers = new Phaser(5);
            Consumer l1 = new Consumer("Consumer_1");
            l1.setDaemon(true);
            l1.start();
            Consumer l2 = new Consumer("Consumer_2");
            l2.setDaemon(true);
            l2.start();
            Consumer l3 = new Consumer("Consumer_3");
            l3.setDaemon(true);
            l3.start();
            Consumer l4 = new Consumer("Consumer_4");
            l4.setDaemon(true);
            l4.start();
        }
    
        class Consumer extends Thread {
    
            Consumer(String name) {
                super(name);
            }
    
            private void printMethod(String i) {
                System.out.println(Thread.currentThread().getName() + " " + i);
            }
    
            public void run() {
                while (true) {
                    //make the consumers sleep till producer produces
                    consumers.arriveAndAwaitAdvance();
                    for (int i = 0; i < array.length; i++) {
                        printMethod(array[i]);
                    }
                    //alert the producer to start 
                    producer.arriveAndAwaitAdvance();
                    System.out.println(Thread.currentThread().getName() + " thread wakeup but will stuck with consumers.arriveAndAwaitAdvance!");
    
                }
            }
        }
    
        public void run() {
            for (int j = 0; j < 3; j++) {
                array = new String[5];
                for (int i = 0; i < array.length; i++) {
                    array[i] = "Phase_" + (j + 1) + " Count_" + (i + 1);
                }
                System.out.println("Main thread pushed data.");
                //alert the consumers to start 
                consumers.arriveAndAwaitAdvance();
    
                //make the producer sleep till all the consumer consumes
                producer.arriveAndAwaitAdvance();   
                System.out.println("Main thread wakeup and will start pushing data...");
    
            }
        }
    
        public static void main(String[] args) {
            ProducerConsumerExample sch = new ProducerConsumerExample();
            sch.init();
            sch.run();
            System.out.println("Main thread completed, producing data.");
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-20
      • 2021-03-27
      • 2016-12-25
      • 2012-07-08
      • 2012-10-11
      • 1970-01-01
      • 1970-01-01
      • 2011-09-11
      相关资源
      最近更新 更多