`

notify notifyAll 和死锁

 
阅读更多

20140217 问题解决: 参考 

第21章 - 并发 - 单一生产者与消费者,多个生产者与多个消费者(P709) 

http://jackyin5918.iteye.com/blog/2018319

 

主要原因是因为使用单一锁,单一条件,使用Lock 创建两个Condition 根据不同条件调用不同condition.的signalAll()方法.

 

下面这个代码参考:http://www.cnblogs.com/Gordon-YangYiBao/archive/2012/09/16/2687520.html

原文说用notifyAll替代notify可解决死锁,其实不行,还是死锁,解决方法还未实现

 

package com.app.thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 
 * 辅助类OutTurn的一个方法输出基数,一个方法输出偶数,两个方法均有通过同步交替输出.
 * 同步条件isOdd==true是输出基数,isOdd==false输出偶数
 * 主类LockDemo,中实现两个runnable,OddPrinter和EvenPrinter分别输出基数和偶数
 * 
 */
public class LockDemo
{
  private static final OutTurn ot = new OutTurn();

  public static void main(String[] args)
  {
    // System.out.println("lock");
    ExecutorService service = Executors.newCachedThreadPool();
    for (int j = 0; j < 10000; j++) //这里要循环次数大一些的,否则不容易出现死锁
    {
      service.submit(new OddPrinter());
      service.submit(new EvenPrinter());
    }
    service.shutdown();
  }
  
  /**
   * printEven (((((((((((( 5202
     printOdd ---- 5203
     printEven (((((((((((( 5204
     printOdd ---- 5205
     printEven (((((((((((( 5206
   * 运行到上面时卡住了,表示死锁了.
   * 分析: 上面是输出5026后死锁的,此时isOdd=true,然后调用notify方法,此方法
   * 唤醒一个线程(其他线程都处于等待状态),假如唤醒的线程还是EvenPrinter,则此线程会立即
   * 执行
   * while (isOdd)
      {
        this.wait();
      }
      此时,这个唯一的唤醒的线程也处于等待状态,然后 所有线程都处于等待状态了,然后导致死锁.
      
      将所有的notify方法换成notifyAll方法 还是不行
   *
   */

  static class OddPrinter implements Runnable
  {
    @Override
    public void run()
    {
      ot.printOdd();
    }
    
  }

  static class EvenPrinter implements Runnable
  {
    @Override
    public void run()
    {
      ot.printEven();
    }
  }
}

class OutTurn
{
  private boolean isOdd = true;
  private int     count = 1;

  public synchronized void printOdd()
  {
    try
    {
      while (!isOdd)
      {
        this.wait();
      }
      System.out.println("printOdd ---- " + count);
      isOdd = false;
      this.notifyAll();
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
    count++;

  }

  public synchronized void printEven()
  {
    try
    {
      while (isOdd)
      {
        this.wait();
      }
      System.out.println("printEven (((((((((((( " + count);
      isOdd = true;
      this.notifyAll();
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
    count++;
  }

}

 

分享到:
评论
2 楼 jackyin5918 2014-02-20  
kuaile777.happy 写道
楼主,你这看的是哪本书啊

这个不是书里面的,是
http://www.cnblogs.com/Gordon-YangYiBao/archive/2012/09/16/2687520.html 里面说的的问题,我改了下代码,发现原来文章中的解决方法并不能解决问题.

第21章 - 并发 - 单一生产者与消费者,多个生产者与多个消费者(P709)
这个文章是来自 Java 编程思想 代码我也改了一下
1 楼 kuaile777.happy 2014-02-20  
楼主,你这看的是哪本书啊

相关推荐

    源码—Java多线程5—死锁和wait notify notifyAll

    源码—Java多线程5—死锁和wait notify notifyAll

    Java 同步方式 wait和notify/notifyall

    在Java中,`wait()`, `notify()`, 和 `notifyAll()` 是Java Object类的三个方法,它们在实现线程间通信和协作时扮演着关键角色。这些方法主要用于解决线程等待和唤醒的问题,是基于Java Monitor(监视器)模型的。 ...

    基于Java多线程notify与notifyall的区别分析

    总结来说,`notify()`和`notifyAll()`之间的主要区别在于唤醒线程的数量和死锁的风险。`notify()`仅唤醒一个线程,可能导致死锁或不一致的状态,而`notifyAll()`唤醒所有线程,尽管可能增加资源消耗,但在多数情况下...

    java notify和notifyAll的对比

    Java中的`notify`和`notifyAll`方法是多线程编程中的重要概念,它们都是`Object`类的方法,用于在同步控制中唤醒等待在特定对象监视器上的线程。理解这两个方法的区别对于编写高效的并发代码至关重要。 首先,`...

    Java的wait(), notify()和notifyAll()使用心得

    4. **死锁和饥饿**:虽然`wait()`, `notify()`, `notifyAll()` 提供了线程间的通信,但不当使用可能导致死锁(两个或更多线程互相等待对方释放资源而无法继续执行)或饥饿(某些线程一直无法获取资源而无法执行)的...

    深入理解Wait、Notify和Wait与sleep区别

    它们提供了一种精细控制线程间交互的方式,但使用时需谨慎,避免死锁和活锁的发生。 总之,理解和熟练掌握`wait()`, `notify()`以及`sleep()`的使用对于编写高效的多线程程序至关重要。在设计并发程序时,应根据...

    wait,notify等线程知识.pdf

    使用wait/notify机制时,需要注意死锁和活锁问题。死锁发生在两个或更多线程互相等待对方释放资源的情况下。活锁则是线程不断尝试获取资源但一直失败,导致无限期阻塞。合理设计同步策略和避免这些情况是多线程编程...

    java中几个notify、wait使用实例

    `wait()`、`notify()`和`notifyAll()`方法是Java中实现线程同步的关键工具。正确使用它们可以有效避免线程间的竞争条件和死锁问题,同时也能实现线程间的高效通信。在实际开发中,应根据具体的应用场景选择合适的...

    Java源码房门终于被打开了(解决死锁的方法).rar

    在Java中,死锁通常与多线程同步有关,尤其是当使用synchronized关键字和wait()、notify()、notifyAll()方法时,如果没有正确管理,就可能导致死锁的发生。 死锁的四个必要条件是: 1. 互斥条件:至少有一个资源是...

    等待机制与锁机制wait notify

    此外,为了防止死锁和饥饿现象,合理地设计同步策略和唤醒逻辑至关重要。 总结来说,`wait`、`notify`和`notifyAll`是Java多线程中实现线程间通信的关键工具,它们允许线程在适当的时候释放资源并等待,以便其他...

    java多线程之wait(),notify(),notifyAll()的详解分析

    Java多线程编程中,`wait()`, `notify()`, 和 `notifyAll()` 是三个非常重要的方法,它们用于线程间通信和同步。这些方法并不是定义在 `Thread` 类中的,而是作为 `Object` 类的一部分,这意味着任何Java对象都可以...

    Java中的notyfy()和notifyAll()的本质区别

    在Java多线程编程中,`notify()`和`notifyAll()`是两个非常关键的方法,它们用于线程间的通信,特别是与`wait()`方法配合使用时,可以实现线程的同步和协作。这两个方法都是`Object`类的方法,因此所有Java对象都...

    操作系统课程设计 死锁环路检测

    Java提供了如`synchronized`关键字、`wait()`、`notify()`和`notifyAll()`等工具来管理线程间的同步与通信,防止死锁的发生。 死锁的四个必要条件包括: 1. 互斥:至少有一个资源在任何时候只能由一个进程使用。 2....

    一个理解wait()与notify()的例子

    - 调用`b.wait()`,这会让当前线程进入等待状态,直到另一个线程调用`b.notify()`或`b.notifyAll()`唤醒它。 - 输出完成后的总和。 - **`ThreadB`类**: - 继承自`Thread`类,重写了`run`方法。 - 在`run`方法...

    Java多线程与并发系列22道高频面试题(附思维导图和答案解析)

    notify可能会导致死锁,而notifyAll则不会。notifyAll可以唤醒所有处于wait状态的线程,使其重新进入锁的争夺队列中,而notify只能唤醒一个线程。 四、sleep和wait的区别 sleep和wait都是用于线程暂停执行的方法,...

    Java 同步锁 wait notify 学习心得

    正确使用这些方法可以有效避免线程间的死锁和资源浪费,同时保证多线程程序的正确性和性能。然而,使用这些方法时也需谨慎,不当的使用可能导致线程饥饿或其他并发问题。因此,深入理解Java的线程模型和锁机制是编写...

    一家三口共用同一账户银行卡,wait();notify();

    5. **线程安全**:通过使用synchronized关键字和wait/notify机制,保证了在多线程环境下,存款和取款操作的正确性,避免了数据竞争和死锁等问题。 6. **线程启动**:通过调用`Thread.start()`启动线程,使得新线程...

    Java 实例 - 死锁及解决方法源代码+详细指导教程.zip

    使用`wait()`、`notify()`和`notifyAll()`方法进行线程间的通信,可以避免因资源争夺造成的死锁。 9. **资源有序分配策略**: 对于可能出现死锁的资源,强制规定线程必须按照一定的顺序请求资源,从而打破循环...

    多线程同步和通讯完整示例

    - 使用wait、notify和notifyAll时,应避免死锁和活锁。 ### 三、Lock接口 Java 5引入了java.util.concurrent.locks包,其中的Lock接口提供了比synchronized更细粒度的锁控制。Lock接口提供了一些额外的功能,如可...

    JAVA多线程 竞态条件、死锁及同步机制.docx

    而其他线程可以通过 `notify()` 或 `notifyAll()` 来唤醒等待的线程。 3. **Lock 接口(ReentrantLock)**:自 Java 5 引入,提供了更细粒度的锁控制。`ReentrantLock` 是 Lock 接口的实现类,提供了 `lock()`、`...

Global site tag (gtag.js) - Google Analytics