本文共 1653 字,大约阅读时间需要 5 分钟。
java代码
package com.baigu.demo1;public class TestWaitNotify { public static void main(String[] args) throws Exception{ Object o = new Object(); SubThread t = new SubThread(o); t.start(); synchronized (o){ //wait方法需要放在同步代码块中 主线程拿到o的锁 System.out.println("main 1"); o.wait(); //主线程进入对o的等待队列 并且释放主线程拥有的所有锁标记 System.out.println("main 2"); } }}class SubThread extends Thread{ Object o; public SubThread(Object o) { this.o = o; } public void run(){ synchronized (o){ System.out.println("Sub 1"); o.notifyAll(); //将主线程释放出来 但是不会释放该线程拥有的锁标记 System.out.println("Sub 2"); //run方法结束 主线程才能拿到o的锁标记 } }}
执行结果
一个线程可以同时拥有多个对象的锁标记,意味同步代码块是可以嵌套的死锁问题
解决办法 调用wait notify notifyAll方法
个人理解synchronized关键字 解决多线程并发访问同一对象破坏原子操作造成数据不一致问题。线程拿到对象的锁标记一个线程可以同时拥有多个对象的锁标记,意味同步代码块是可以嵌套的,当线程阻塞在锁池时,线程不会释放它已经拥有的对象锁标记(除非run方法结束),会造成死锁问题。java中任何一个对象都有一个锁标记 锁池 等待队列线程间通信: 等待-通知任何对象都有一个等待队列,用来存放线程。Object wait()t1: o.wait() 必须放在对o加锁的同步代码块中。会有两种结果 1.t1会释放其拥有的所有锁标记2.同时t1会阻塞在o的等待队列中 (t1对o调用wait()方法)t2: o.notify()/notifyAll() 必须放在对o加锁的同步代码块中,从o的等待队列中释放一个/全部线程(t2.对o调用notify()或者是notifyAll()方法)线程对对象调用wait() 方法进入该对象的等待队列中,靠别的线程对该对象调用notify()或者是notifyAll()方法进行从该对象的等待队列中进行释放该线程ArrayList 线程不安全 :所有的方法都不是同步方法Vector 线程安全 :所有的方法都是同步方法HashMap: 线程不安全 :所有的方法都不是同步方法HashTable: 线程安全 :所有的方法都是同步方法线程不安全:访问临界资源造成数据不一致修饰符组合:synchronized 和 static联用:是给当前类对象加锁,staitc修饰方法没有this.(因此没有当前对象)synchronized 和 abstract联用: 不可以 没有意义,抽象方法没有代码块,synchronized修饰的是代码块synchronized 和 构造方法联用:不可以 同步方法对当前对象加锁,而构造方法中当前对象还没有构造结束,无法使用里面互斥锁标记
这辈子坚持与不坚持都不可怕,怕的是独自走在坚持的道路上! 欢迎加入技术群聊!
转载地址:http://ikoai.baihongyu.com/