Java线程相关

Java本身就是个支持多线程的语言

每个Java程序就是一个进程,进程又分线程

进程之间是完全相互隔离的,但是同一个进程的各线程之间,又存在着空间公用和数据共享

 

 程序计数器私有:保证线程切换后能回到正确的位置继续执行

本地方法栈和虚拟机栈私有:保证线程中的局部变量不被其它线程访问到

堆和方法区为线程共享。堆主要存储程序执行过程中创建的对象;方法区主要存放已被加载的对象、常量、静态变量等

 

多线程的优点:多线程可以提高系统的执行效率,特别是多OI或者在多核CPU上时,使用多线程能充分发挥CPU的性能,避免CPU过多的空闲

多线程的问题:线程的切换需要CPU资源,整体上增加了CPU开销;多线程可能造成内存泄露、死锁、线程不安全等问题

 

线程的状态:初始状态、运行状态、阻塞状态、等待状态、超时等待状态、中止状态

  初始状态:线程被创建出来,但是还没start();

  运行状态:线程调用start()等待运行的状态;

  阻塞状态:线程被阻塞,等待锁释放的状态;

  等待状态:线程需要等待其它线程做一些动作,如通知、中断等;

  超时等待状态:线程可以在一定时间后自行返回,而不是一直傻傻的等待;

  中止状态:线程已运行完毕;

初始状态调用start()方法,线程进入运行状态,如果需要获取锁,线程进入阻塞状态,等待获取到锁,则继续运行。需要线程间互相配合时,线程可能回到等待状态,等待其它相关线程执行完毕。也可手动设置线程的等待时间,线程便进入超时等待状态,等待时间已过,便再次进入运训状态。线程执行完毕,即为中止状态。

 

上下文切换

  线程调用了sleep()、swit()等方法

  线程的时间片用完

  线程调用了IO操作,线程被阻塞

此时线程后保留当前线程的上下文,让出CPU,并加载下一个将要执行线程的上下文

 

死锁:

  死锁就是多个线程各自占用了部分系统资源,同时又没有全部拿到自己所需要的全部资源,导致所有线程都在等待对方首先释放资源,互相等待。

  死锁形成的条件:1、资源互斥,一个资源同一时间只能由一个线程使用;2、请求与保持条件,线程因请求资源而阻塞时,不释放以获得的资源;3、资源只能由本线程释放,不能被其它线程剥夺;4、各线程间等待形成环状

  预防死锁:1、一次请求所有资源,否则就释放所有资源;2、占用资源的线程申请其它资源失败时,释放已有的资源;3、按序申请资源

 

sleep()和wait()

sleep()仅仅相当于使线程暂停执行,并不释放资源,到时自动唤醒继续执行

wait():线程中止执行,进入等待状态,并释放锁,且线程不会自动唤醒,需要调用同一个对象上的notify()或notifyAll()方法唤醒,使用wait(time)也可以到时自动唤醒

sleep()是Theath类的静态本地方法,wait()是Object类本地方法

wait()是让获得对象锁的线程实现等待,释放当前线程所占用的对象锁,既然要释放对象锁,自然要操作对象

sleep()仅仅是让线程等待,涉及不到对象

 

new一个Thread,线程进入新建状态,如果执行线程的start()方法,会启动一个线程,并进入就绪状态,当时间片到了之后,就会自动运行run()方法,执行线程。start()会做线程的准备工作,之后执行run()。

但是,如果直接执行run()方法,则仅仅是相当于在main线程中执行了一个普通方法,不是多线程的操作。

 

volatile关键字

  volatile关键字修饰变量表示变量是共享且不稳定的,禁用线程缓存,线程每次使用该变量都需要到主存中读取;同时该关键字也能阻止指令重排序;volatile关键字不能保证数据的原子性

synchronized关键字修饰实例方法、静态方法、代码块,能保证方法的原子性

  实例方法:锁当前对象的实例

  静态方法:锁当前对象

  代码块:锁指定对象、类或者代码块

  构造方法本身就是线程安全的,不能使用synchronized关键字

voattile是synchronized的轻量级实现,性能要优于synchronized,但是volatile只能保证数据在线程间的可见性,不能保证数据的原子性,而synchronized两者都能保证;volatile只能修饰变量,synchronized还能修饰方法和代码块

 

乐观锁和悲观锁

乐观锁是假设最好的情况,认为资源被共享也不会出问题,不限制线程对资源的读取,只有在会资源修改进行提交时,才校验资源是否已被其它资源修改,如果是,本次修改失败,如果不是,则本次修改成功。主要用于对资源读操作比较多的场景‘

悲观锁总是假设最坏的情况,认为资源一旦被访问就会被修改,每次读取资源时都会枷锁,但是修改资源时将不再校验资源版本。主要用在修改比较多的场景下。如synchronized就是悲观锁的实现

乐观锁可以用版本号机制或者CAS算法判断资源是否被其它线程修改

 

posted @ 2023-03-20 23:27  再见残月  阅读(10)  评论(0编辑  收藏  举报