做网站 宁波,seo外推上排名,谁做视频网站,网页美工设计网课前言 前面我们说到了死锁以及线程可见性的问题 我们将线程可见性主要归结于是JVM自身的一个bug 一个线程写一个线程读 会将一直不变的变量优化到直接从寄存器中读取,而不是缓存等读取,因为这样我们就设置了使用volatile关键字使得用到这个变量的时候必须从内存中读取数据 死锁主…前言 前面我们说到了死锁以及线程可见性的问题 我们将线程可见性主要归结于是JVM自身的一个bug 一个线程写一个线程读 会将一直不变的变量优化到直接从寄存器中读取,而不是缓存等读取,因为这样我们就设置了使用volatile关键字使得用到这个变量的时候必须从内存中读取数据 死锁主要是四个原因导致:不可抢占,互斥使用,循环等待,请求保持 其中只有循环等待是最好破坏的,我们可以使用规定线程的加锁顺序来破坏这种循环等待的效果 本节我们将讨论wait和notify两个方法的使用 为什么引入这两个方法,有什么用? 和join方法类似,这两个方法还是用来在应用层面上规定代码的执行顺序,事实上在操作系统内核中线程的调度仍然是无序的 这里的干预其实就是让某个线程主动放弃了去cpu执行的权利,相当于放弃了被调度的机会 举个例子: 此时a线程想去atm中取钱,b线程和c线程想进去存钱,恰好此时a拿到了锁,进去了atm房间 此时a就可以一直占用atm机器等待,加入发现没钱出来,a仍然在行列中竞争锁,所以a一直能持有锁(概率问题,就像我跟你分手了,我们复合的概率更大一样),此情况就称之为线程饿死,因为其他的线程都拿不到锁,执行不了自己的代码 (就是某个线程一直反复获取锁,但是又不执行实质性的逻辑) wait做了什么?? wait方法实际上是做了三件事情 1.释放锁 2.阻塞等待 3.当其他线程调用notify方法的时候,解除阻塞状态,持有锁之后继续运行代码 join和notify的区别 join方法是指假如在主线程中调用t1.join 此时主线程就会等t1线程执行完才会继续执行 而wait方法除非有线程去唤醒他,他会一直等到枯树开出花 当然,我们也是可以设置wait的最大时间的,也就是等不到结果就直接不等了 产生阻塞的几种原因 join/wait BLOCKED sleep TIMED_WAITING synchronized BLOCKED 由于wait是object类中的一个方法,所以随便拿个对象都可以使用wait方法,但是得持有锁才行,不然会发生异常 我们一般在synchronized代码块中使用 注:调用wait的对象一般和synchronized的锁一致 一个简单的使用案例 public static void main(String[] args) {//统一对象进行加锁解锁Object lock new Object();Thread t1 new Thread(()-{synchronized (lock){System.out.println(t1 wait 之前);try {lock.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println(t1 wait 之后);}});Thread t2 new Thread(()-{synchronized (lock){try {Thread.sleep(5000);System.out.println(notify之前);lock.notify();System.out.println(notify之后);} catch (InterruptedException e) {throw new RuntimeException(e);}}});t1.start();t2.start();} 此时的结果就是,t1线程在执行过打印效果后,会进入阻塞状态,然后t2睡眠5000ms之后会执行一次打印动作,然后让t1解除阻塞状态,最后执行完下一次打印后释放锁 注:notify方法只会唤醒阻塞的线程,并不会释放锁 注:wait和notify方法是成套使用的,两者依靠对象联系起来 假如这里我们使用object1对象来wait这个线程 再使用objcet2是唤不醒这个线程的 多线程知识点小结 1.线程的特性,线程和进程的区别 2.Thread类创建线程的几种方式 3.Thread类的一些属性 4.启动线程 5.终止线程 6.等待线程 7.线程休眠 8.获取线程引用 9.线程状态 10.线程安全问题 10.1 线程安全产生的原因及解决方法 10.2 死锁问题 10.3 内存可见性问题 11.线程的wait和notify...