Java并发学习笔记(一)

2022-03-24 15:25:06 浏览数 (1)

Java并发学习笔记(一)

为什么需要并行?

-业务需求

-性能

并行和并发

并行:两条线程一起跑 (多核)

并发:两条线程交替跑 (单核)

临界区

表示一种公共资源或者说是共享数据,可以被多个线程使用。但是每一次,只有一个线程使用它,一旦临界区资源被占用,其他线程想要使用这个资源,就必须等待;

阻塞和非阻塞

阻塞和非阻塞通常用来形容多线程间的相互影响;比如一个线程占用了临界区资源,那么其他所有需要这个资源的线程就必须在这个临界区中进行等待,等待会导致线程挂起,这种情况就是阻塞;此时,如果占用资源的线程一直不愿意释放资源,那么其他阻塞在这个临界区上的线程都不能工作;

非阻塞允许多个线程同时进入临界区;

死锁、饥饿和活锁

死锁:指两个或两个以上的进程(或线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程;静态问题

产生死锁的必要条件:

代码语言:javascript复制
-互斥使用 

-循环等待

-不可被剥夺

-占有且等待 

饥饿:指一个或多个线程因为种种原因无法获得所需要的资源,导致一直无法执行;

活锁:任务或者执行者没有被阻塞,由于某些条件没有满足,导致一直重复尝试,失败,尝试,失败;

比如:线程A和B都需要过桥(都需要使用进程),而都礼让不走(那到的系统优先级相同,都认为不是自己优先级高),就这么僵持下去.

并发级别:

-阻塞 当一个线程进入临界区后,其他线程必须等待

以下三种统称非阻塞

-无障碍 无障碍是一种最弱的非阻塞调度;自由出入临界区;无竞争时,有限步内完成操作,有竞争时回滚数据;

-无锁 必须是无障碍的,保证有一个线程可以胜出

-无等待 是无锁的,要求所有的线程必须在有限步内完成,无饥饿的; (例:所有的读线程)

加速比=优化前系统耗时/优化后系统耗时

总结: 提高程序可串行化的比重和合理增加cpu

多线程基础

什么是线程?

线程是进程内的执行单元;

线程的基本操作

线程中断

代码语言:javascript复制
Thread.interrupt()//中断线程

Thread.isInterrupted//判断是否被中断

Thread.interrupted//判断是否被中断,并清除当前中断状态

守护线程

代码语言:javascript复制
在后台默默地完成一些系统性服务,比如垃圾回收线程、JIT线程就可以理解为守护线程

当一个java程序只有守护线程时java虚拟机就会自动退出;

线程优先级

设置优先级setPriority()

基本的线程同步操作

synchronized

代码语言:javascript复制
指定加锁对象:给定对象加锁,进入同步代码块前要获得给定对象的锁

直接作用于实例方法:相当于对当前实例加锁,进入同步代码块前要获得当前实例的锁

直接作用于静态方法:相当于对当前类加锁,进入同步代码块前要获得当前类的锁

Object.wait() Object.notify()

Java内存模型和线程安全

原子性

代码语言:javascript复制
原子性是指一个操作是不可中断的。即使在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰;

i  是原子操作么?  不是,读取i的值、  、写回;

有序性

代码语言:javascript复制
     即程序执行的顺序按照代码的先后顺序执行。 

     处理器有指令重排;

可见性

代码语言:javascript复制
可见性是指当一个线程修改了某一个共享变量的值,其他线程是否能够立即知道这个修改;

-编译器优化

-硬件优化(如写吸收,批操作)

Happen-Before规则

代码语言:javascript复制
程序顺序原则:一个线程内保证语义的串行性 ; 保证重排之后的结果与重排之前保持一致;  a=1;b=a 1;

volatile规则:volatile变量的写,先发生于读,这保证了volatile变量的可见性;

锁规则:解锁(unlock)必然发生在随后的加锁(lock)前;

传递性:A先于B,B先于C,那么A必然先于C

线程的start()方法先于它的每一个动作;

线程的所有操作都先于线程的终结(Thread.join);

线程的中断(interrupt())先于被中断线程的代码

对象的构造函数执行结束先于finalize()方法;

0 人点赞