欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

多线程学习 等待队列状态 死锁问题及其解决办法 五

程序员文章站 2022-05-04 18:51:07
...

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 和 构造方法联用:不可以 同步方法对当前对象加锁,而构造方法中当前对象还没有构造结束,
无法使用里面互斥锁标记

这辈子坚持与不坚持都不可怕,怕的是独自走在坚持的道路上! 欢迎加入技术群聊!

多线程学习 等待队列状态 死锁问题及其解决办法 五

相关标签: 多线程