zoukankan      html  css  js  c++  java
  • java synchronized wait

    在多个线程要互斥访问数据,
    但线程间需要同步时——例如任务分多个阶段,特定线程负责特定阶段的情况,
    经常合作使用synchronized 和 wait()

    /**
     * 
     * 计算输出其他线程锁计算的数据
     * @author 
     *
     */
    public class Main {
        public static void main(String[] args) {
            ThreadB b = new ThreadB();
            b.start();// 启动计算线程
            synchronized (b) {
                try {
                    System.out.println("等待对象b完成计算...");// 当前线程A等待
                    b.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("b对象计算的总和是:" + b.total);
            }
        }
    }
    public class ThreadB extends Thread {
        int total;
    
        public void run() {
            synchronized (this) {
                for (int i = 0; i < 101; i++) {
                    total += i;
                }  
                //计算操作结束      
                notify();//唤醒在此对象监视器上等待的单个线程,在本例中线程A被唤醒
            }
        }
    }

    synchronized(b)导致了b上开启了同步锁。也就是说
    只要存在 synchronized (b) 就会等待解锁。
    也就是说A里的synchronized(b) {} 就是为了防止在执行的时候B里的synchronized(this){ } 代码段同时执行。

    来个时间线。
    1. A: synchronized (b) {
    (这时候拿到b的锁,其他同步段不能执行,在等待中)
    2.      try {
              System.out.println("等待对象b完成计算。。。");
              b.wait();
              (这时候A放弃b锁,让B执行)
    3. B: synchronized (this) {
                for (int i = 0; i < 101; i++) {
                    total += i;
                }
                notify();
                (唤醒A)
    4. A:继续执行。


    还可以用于方法前标示同步方法
    比如:
    public synchronized void methodA(){}
    wait()是Object的方法,意味着所有的对象都有这个方法。
    调用这个方法时表示执行这个方法的当前线程放弃执行,进入等待状态,同时放弃对象锁,其它线程就可以进入由同一个对象锁控制的同步块或同步方法。

    wait()时会先释放当前线程所拥有的锁,
    当从wait状态返回时,会再次获取之前的锁,之后再执行后续代码。
    这点由JVM保证,可查JDK文档。

    为什么wait()一定要在同步方法或同步块中调用?
    这是因为wait()命令的发出者必须首先拥有锁,或者说只有手中持有锁的线程才有资格等待以交出控制权。wait()/notify()这种机制的引入本身就是为了在资源独占(表现为synchronized)的前提下合作,所以只有配合锁使用才有意义。


    wait()/notify()是相互协作的,刚开始怎么想也想不明白要独占资源
    现在想了一下,好像有点眉目了:
    一个线程计算结果,另外一个线程等待结果,但是两个线程都要访问某个共同变量,一个线程往里放结果,另外一个线程从中取结果。上面例子的total就是共同变量。因为要访问共同变量,所以涉及到资源独占的问题,所以要加上synchronized关键字。
       

    wait()促使当前线程放弃锁,其他等待线程可以拿到锁了
    sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

     http://bbs.csdn.net/topics/330005504

  • 相关阅读:
    最小的K个数
    堆排序
    归并排序
    希尔排序
    快速排序
    二分查找
    数组中出现次数超过一半的数字
    包含min函数的栈
    栈的压入、弹出序列
    中缀表达式转后缀表达式
  • 原文地址:https://www.cnblogs.com/softidea/p/3820654.html
Copyright © 2011-2022 走看看