zoukankan      html  css  js  c++  java
  • Java并发之(2):线程通信wait/notify(TIJ_21_5)

    简介:   

    java中线程间同步的最基本的方式就是使用wait()&notify()&notifyAll(),它们是线程间的握手机制。除了上述方法,java5还在java.util.concurrent.Locks包中提供了condition接口,该接口声明了awake()&signal()方法,也是线程间同步的方式之一。 wait()/notify() 都是任意java object所具备的方法,它们通常与synchronized关键字配合使用,而condition一般与显式的重入锁配合使用。

    语义:

       Object.wait()把当前线程挂起,等待object.notify()或者object.notifyall()的执行。wait()可以替代busy waiting(通常以循环查询某条件是否已经具备的方式)。

    object.notify()把等待object锁(monitor)的线程唤醒,通知其可以继续运行。如果有多个线程都在等待这个object的锁,则随机选择一个唤醒同时当前线程继续执行当另外一个线程调用该java对象的notify()方法时,将“唤醒”等待该java对象的那个线程。

    notifyAll()将唤醒所有在等待的线程;notify()仅唤醒一个正在等待的线程,如果有多个线程在等待,会随机选择一个唤醒。

    Wait:

    为了正确地执行object.wait()方法,当前线程必须已经获得了该object的锁。也就是说,只有在同步方法或者同步块(synchronized)中,才能调用wait方法。执行object.wait()方法意味着当前线程释放该锁,当前线程挂起,直到有另外线程执行object.notify()方法。  wait()有三种方式,带纳秒参数的::

    1  public final void wait(long timeout, int nanos) throws InterruptedException {

    带毫秒参数的 :

    1  public final native void wait(long timeout) throws InterruptedException;

    和不带参数的:

    1  public final void wait() throws InterruptedException {

    其中wait()使用的比较多。

    纳秒级的等待?

    看wait的第一种实现,很有意思:

     1     public final void wait(long timeout, int nanos) throws InterruptedException {
     2         if (timeout < 0) {
     3             throw new IllegalArgumentException("timeout value is negative");
     4         }
     5 
     6         if (nanos < 0 || nanos > 999999) {
     7             throw new IllegalArgumentException(
     8                                 "nanosecond timeout value out of range");
     9         }
    10 
    11         if (nanos > 0) {
    12             timeout++;
    13         }
    14 
    15         wait(timeout);
    16     }

     nanos好像并没有发挥什么作用。 这是Java8在Windows平台下的JDK的源码。注意如果是实时操作系统的话,nanos就有可能发挥作用,但是在Windows下,nanos目前并没有发挥作用。这是因为虽然cpu的时钟周期是纳秒级的,但是Windows操作系统并不支持这么细粒度的时间间隔。

    在调用wait时还有一点要特别注意:

     永远在一个循环中调用wait()方法。因为如果多个线程都在等待同一个锁,然后其中一个得到了这个锁,然后会重置等待的条件,然后其他线程需要在它们醒来以后检查循环条件,以此来决定它们是需要再次等待,还是开始执行。

    notify:

    为了调用某个java对象的notify()方法,你必须在同一个java对象上同步(synchronized),或者说在一个同步的上下文中:

    1 synchronized (someObject) {
    2     someObject.wait(); // 释放锁,不对。应该在一个循环中调用wait方法
    3 }
    4 
    5 /* different thread / object */
    6 synchronized (someObject) {
    7     someObject.notify();
    8 }

     

    尽量少使用wait/notify:

    从Java5开始,java sdk中的java.util.conconrrent包中主要提供了三种与线程同步(不是synchronization,不是lock之类的线程互 斥)相关的类: Executor相关框架、并发容器(BlockinQueue)、和一些同步工具(Synchronizers,倒计数锁存器等)。这些同步工具主要是通用的同步类,主要用于线程间的协作。同步工具主要包括Condition、CountdownLatch、CyclicBarrier、Semaphore、CyclicBarrier、phasersexchangers等。

    一般而言,在java5或者更新的java版本中,wait()&notify()很少显式地使用。因为很多标准库中的类已经实现了wait()/notify()的功能。比如:

    • 在Java5中,可以使用新的BlockingQueue实现,来实现生产者和消费者模型。
    • Java5中的显式锁类,比标准的synchronized关键字提供了更多的功能,比如带超时的tryLock。在Java5之前这个功能需要使用 wait()/notify()才能实现;
    • 可以使用Semaphore控制资源池。

    操作系统线程问题中的概念

    关键段CS critical section、事件Event、互斥量Mutex  信号量等概念 如何与java多线程中的概念映射???

    互斥量:

    跟锁的概念十分类似。

    信号量:

    操作系统的信号量是个很重要的概念,在进程控制方面都有应用。Java 并发库 的Semaphore 可以很轻松完成信号量控制,Semaphore可以控制某个资源可被同时访问的个数,acquire()获取一个许可,如果没有就等待,而 release()释放一个许可。比如在Windows下可以设置共享文件的最大客户端访问个数。

    Semaphore维护了当前访问的个数,提供同步机制,控制同时访问的个数。在数据结构中链表可以保存“无限”的节点,用Semaphore可以实现有限大小的链表。另外重入锁ReentrantLock也可以实现该功能,但实现上要复杂些,代码也要复杂些。

    参考文献:

    http://blog.csdn.net/zyplus/article/details/6672775

    http://javamex.com/tutorials/synchronization_wait_notify.shtml

    http://www.javamex.com/tutorials/synchronization_producer_consumer.shtml

    http://www.javamex.com/tutorials/synchronization_producer_consumer_2.shtml

    http://www.javamex.com/tutorials/synchronization_concurrency_semaphore.shtml

    http://blog.csdn.net/zyplus/article/details/6672775

    http://www.javamex.com/tutorials/synchronization_wait_notify.shtml

    http://blog.csdn.net/morewindows/article/details/7481609

    http://blog.csdn.net/morewindows/article/details/7442639

    http://blog.csdn.net/morewindows/article/details/7445233

    http://blog.csdn.net/morewindows/article/details/7442333

    http://stackoverflow.com/questions/6553225/whats-the-purpose-of-sleeplong-millis-int-nanos

  • 相关阅读:
    用X++读取文本文件(txt文件)的例子
    找出整个AX系统使用某个扩展类型的所有表和字段
    关于代码操作AOT
    检查所有表Relations是否为unknown
    strSplit分隔文本以container返回
    POJ 1850, Code
    用匈牙利算法求二分图的最大匹配(转载)
    POJ 2533, Longest Ordered Subsequence
    POJ 1159, Palindrome
    POJ 3252, Round Numbers
  • 原文地址:https://www.cnblogs.com/hzg1981/p/5038101.html
Copyright © 2011-2022 走看看