首页 > 其他分享 >m2_day05 [线程]

m2_day05 [线程]

时间:2024-05-10 23:41:43浏览次数:17  
标签:锁池 synchronized 标记 对象 t2 day05 线程 m2

课程内容:
  • 什么是并发错误?

  • 如何解决并发错误?

  • 什么是死锁?

  • 如何解决死锁?

  • 锁池和等待池的区别


什么是并发错误?
  • 并发错误的概念

    多个线程共享操作同一份数据的时候
    线程体当中连续的多行操作 未必能够连续执行
    很可能操作只完成另一部分 时间片就突然耗尽
    此时 另一个线程抢到了时间片
    直接访问了操作不完整的数据
  • *: 并发修改异常 和 并发错误 什么关系?

    并发修改异常 是Sun公司官方的程序员
      主动判断 主动校验 主动抛出的一个运行时异常
      它的主要目的 就是为了避免程序进一步执行就会导致并发错误
      最大限度的避免并发错误
      (走在荒无人烟的小路上 为了不见鬼 选择拍晕自己..)

如何解决并发错误?
  • 方式一:使用对象的互斥锁

    Java中的每个Object类型的对象都有的五个属性: 属性、方法、锁标记、锁池、等待池。

    互斥锁 = 锁标记 = 互斥锁标记 = 锁旗标 = 监视器 = Monitor

    synchronized = 修饰符 = 形容词 (一定是非公平锁)

    1.修饰代码块
    synchronized(临界资源){
    需要连续执行的操作1;//
    需要连续执行的操作2;
    ...;
    }

    2.修饰整个方法
    public synchronized void add(Object obj){
    需要连续执行的操作1;
    需要连续执行的操作2;
    ...;
    }
    *: 哪怕synchronized加在方法修饰符上
    也是对 对象进行加锁

    *: Vector Hashtable StringBuffer 都是线程安全的
    它们之所以线程安全 是因为
    底层大量的方法使用了synchronized修饰

    *: 单例模式的懒汉式 需要synchronzied修饰那个getter方法

    *: synchronized 有一个其它修饰符都不具备的特性
    它隔代丢失...
    父类的synchronized方法子类能够继承吗?
    能够继承得到这个方法 但是synchronized都不见了
  • 锁标记synchronized的深度理解

    *举例一
    已知: Vector类的add() 和 remove() 都是synchronized修饰的
    我们有一个Vector对象 名叫v
    有两个线程对象 名叫 t1 和 t2
    当t1线程调用v对象的add() 方法已经开始执行了
    但是还没执行结束呢 此时时间片突然耗尽
    t2线程抢到了时间片
    问:
    t2能不能调用v对象的add()? 不能
    t2能不能调用v对象的remove()? 不能

    *举例二
    已知: Hashtable类的put() 和 remove() 都是synchronized修饰的
    我们现在有两个Hashtable对象 名叫 h1 和 h2
    有两个线程 名叫 t1 和 t2

    当t1线程调用h1对象的put() 方法已经开始执行了
    但是还没执行结束呢 此时时间片突然耗尽
    而t2线程抢到了时间片
    问:
    t2线程能不能调用h1对象的put()? 不能
    t2线程能不能调用h1对象的remove()? 不能
    t2线程能不能调用h2对象的put()? 能
    t2线程能不能调用h2对象的remove()? 能
    t2线程能不能调用h2对象的xxxxx()? 能!

    综上所述:
    哪怕synchronized修饰符是加在方法签名上的
    也是对 对象进行加锁
    Java当中每个对象才有锁标记 加锁永远是对对象加锁
    不存在对方法加锁的概念!!
  • 方式二:使用面向对象的可重入锁...since JDK5.0

    java.util.concurrent.locks.ReentrantLock
    Java包的 工具包的 并发包的 锁包的 可重入锁

      lock() unlock()
      加锁   释放锁

    *:ReentrantLock 可以指定公平锁或非公平锁
    new ReentrantLock(true);
    *:公平 = 按照对锁资源申请的先后顺序依次获得

什么是死锁?
互斥锁标记使用过多或者使用不当
就会造成多个线程相互持有对方想要申请的资源
不释放的情况下 又去申请对方已经持有的资源
从而双双进入对方已经持有的资源的锁池当中
产生永久的阻塞

如何解决死锁?
  • 方式一:

        一块空间和三个方法

    一块空间: 等待池
    三个方法: wait() notify() notifyAll()

    wait() : 让当前线程放弃[调用方法的那个对象]的锁标记(主动进入阻塞状态)
    并且进入那个对象的等待池当中阻塞

    notify() : 从[调用方法的那个对象]的等待池
    当中随机的唤醒一个线程

    notifyAll() : 从[调用方法的那个对象]的等待池当中
    唤醒所有阻塞的线程

    *: 它们都必须在已经持有锁标记的前提下才能使用
    也就是说它们一定出现在synchronized{}当中
    也就是说 想要操作对象的等待池 必须先要拿到对象的锁标记
    如果没有拿到锁标记 就直接尝试操作等待池
    不但会操作失败 还会触发
    IllegalMonitorStateException 运行时异常

    *: 它们都是Object类的方法 不是Thread的方法
    因为Java当中每个对象都有等待池
    每个对象都可能需要操作等待池
    所以这三个方法被定义在Object类当中
           
      *举例:
          顺丰陆运 送快递的 不能坐飞机
          大货车不可能只配备一名司机

          王师傅 马师傅
          LeftThread RightThread

          1.开4个小时
          2.主动休息wait()      
                              3.开4个小时
                              4.唤醒王师傅
                              5.主动休息wait()
          6.唤醒马师傅
               
      *理解:
    synchronized{} 申请锁标记
    wait() 归还锁标记 去等待池等待
    notify() 唤醒等待池的进程 并让其进入锁池
    进入锁池的进程 不能立刻进入就绪态 而是   "等待唤醒它的进程wait()后归还锁标记"???
  • 方式二:

锁池和等待池的区别
    锁池和等待池都是Java当中每个对象都有一份的空间

锁池存放的是那些想要申请对象锁标记但是还没有得到的线程
等待池存放的是那些原本已经拿到对象锁标记
但是怕与其它线程相互阻塞 而又主动释放资源的线程

1.进入的时候是否需要释放锁标记
锁池 : 不释放锁标记
等待池 : 先释放持有锁标记

2.离开的时候是否需要调用方法
锁池 : 不需要操作
等待池 : 必须有其它线程notify()/notifyAll()

3.离开之后去往什么状态
锁池 : 返回就绪
等待池 : 进入锁池!!

标签:锁池,synchronized,标记,对象,t2,day05,线程,m2
From: https://www.cnblogs.com/zhaodenghui33/p/18185524

相关文章

  • m2_day2
    课程内容:搭建开发环境配置环境变量第一个程序HelloWorldJava中的软件包结构搭建开发环境:安装jdkwww.Oracle.comSDK=softwaredevelopmentkits=软件开发工具包JDK=java+SDK=java软件开发工具包JRE=javaruntimeenvironment=java运行环境JD......
  • 理解 iOS 中的多线程编程
    在iOS应用开发中,多线程编程是一项关键技术,可以帮助应用实现更好的性能和响应性。本文将详细解释iOS中的多线程编程,并讨论如何在应用中正确地使用多线程以提高性能和响应性。1.什么是多线程编程?多线程编程是指在一个应用程序中同时执行多个线程(线程是进程中的执行单元),从而实......
  • 操作系统线程和Java线程的状态
    操作系统线程和Java线程的状态  一、操作系统线程的状态  操作系统的线程主要有以下三个状态  1. 就绪状态(ready):线程正在等待使用CPU,经调度程序调用之后进入running状态。  2.执行状态(running):线程正在使用CPU。  3.等待状态(waiting):线程经过等......
  • 如果想得到线程中的反悔呢
    importjava.util.ArrayList;importjava.util.List;importjava.util.concurrent.*;publicclassMain{publicstaticvoidmain(String[]args){intcorePoolSize=5;//核心线程数intmaxPoolSize=10;//最大线程数longkeepAlive......
  • 要获取线程池中任务的返回值,可以使用submit()方法返回的Future对象。你可以通过调用Fu
    importjava.util.concurrent.ArrayBlockingQueue;importjava.util.concurrent.ThreadPoolExecutor;importjava.util.concurrent.TimeUnit;publicclassMain{publicstaticvoidmain(String[]args){//设置线程池参数intcorePoolSize=5;//......
  • Java-线程-线程池
    0.背景参考资料:Java线程池实现原理及其在美团业务中的实践在Java早期,每次创建线程时,都要涉及到线程的创建、销毁以及资源管理,这对于系统的性能和资源利用率是一种浪费。因此,Java提供了线程池的概念,以提高线程的管理效率和性能。资源管理优化:传统的线程创建和销毁需要涉......
  • 国密算法SM2-java实现
    Maven依赖<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.56</version></dependency>工具类importjava.math.BigInteger;publicclassUtil{......
  • RR级别-多线程环境下-for update+插入操作包含的间隙锁+插入意向锁引发的死锁问题
    记录selectforupdatemysql死锁问题_执行select...where...forupdate是否会造成死锁(deadlock)-CSDN博客......
  • java 多线程CountDownLatch
     CountDownLatch简介CountDownLatch 是Java中的一个同步工具类,可以用来确保一组线程等待其他线程完成各自工作后再继续执行。CountDownLatch的应用场景CountDownLatch可以被广泛应用于各种多线程协作的场景,例如:主线程等待多个子线程完成后再执行下一步操作。多个子任......
  • 高效C#编程:通过智能线程池管理提升性能
    前言C#编程中,线程池(ThreadPool)是一个重要的概念,它允许开发者更有效地管理和利用系统资源。通过线程池,我们可以避免频繁地创建和销毁线程,从而减少系统开销并提高程序的响应速度和吞吐量。在软件开发中,效率是关键,无论你是在开发一个简单的应用程序还是一个复杂的系统。为了创建一......