线程

线程构造方法:

  1. 设置线程名
  2. 线程的任务
  3. 设置线程分组

线程的常用属性:

ID,Name…状态
优先级(1-10 默认5)
守护线程(后台线程)

守护线程注意:
1.在守护线程里面创建的线程,默认是守护线程
2.守护线程状态的设置必须放在线程启动之前

start和run方法的区别

run属于普通方法,start是启动线程的方法
run方法可以执行多次,start方法只能执行一次

线程中断:

使用全局自定义的变量来终止线程-------------------->收到终止指令后,会执行完当前任务再终止
使用线程提供的终止方法 interrupt 来终止线程---->收到终止指令之后,立马终止

使用线程提供的方法 stop 来终止线程(弃用,终止之后,未释放资源,有安全隐患)

终止线程
Thread.interrupted()方法,判断完线程状态之后,就会将线程状态设置为false;
Thread.currentThread.isInterrupted()方法,执行判断线程终止为true之后,

等待一个线程
join()

获取当前线程引用
currentThread()

线程状态

NEW------------------->新建状态,没有调用start()之前的状态
RUNNABLE---------->运行状态,(running执行中,ready就绪(等待cpu时间片))
BLOCKED------------>阻塞状态,多个线程试图获得同一把锁
WAITING-------------->等待状态,没有明确的等待结束时间,调用wait()
TIMED_WAITING—>超时等待状态,有明确的等待时间,如:sleep(xxx)
TERMINATED-------->终止状态

yield()
出让CPU执行权,特点:不一定能成功出让cpu执行权

线程安全

线程不安全:多线程执行中,程序的执行结果和预期的不相符,就叫做线程不安全

线程非安全

  1. cpu抢占式执行(万恶之源)
  2. 非原子性
  3. 编译器优化(代码优化)编译器优化在单线程下没问题,可以提升程序的执行效率,但是在多线程下就会出现混乱,导致线程不安全问题(指令重排序)
  4. 内存不可见
  5. 多个线程修改了同一个变量

volatile 关键字(轻量级解决“线程安全”)

解决问题:

  1. 强制内存可见(原理:当操作完变量之后,强制删除线程工作内存中的此变量)
  2. 禁止指令重排序

注意:
volatile不能解决原子性问题

解决线程安全:

  1. CPU抢占调度(不能解决)
  2. 每个线程操作自己的变量(可能解决)
  3. 在关键代码上让所有CPU排队执行,加锁;

加锁操作的关键步骤

  1. 尝试获取 (如果成功拿到锁,加锁,没拿到就等待)
  2. 释放锁

Java中解决线程安全问题的方案:

  1. synchronized 加锁和释放锁(JVM层面的解决方案,自动进行加锁释放锁)
  2. Lock 手动锁【程序员自己加锁,释放锁】

Synchronized注意事项:
在进行加锁操作的时候,同一组业务一定是同一个锁对象;

synchronized实现原理:

  1. 从操作来看:互斥锁实现 mutex lock
  2. JVM:monitorenter–>monitorexit实现了监视器的加锁和释放锁的操作
  3. Java:
    a)锁对象:mutex
    b)锁存放的地方:加锁对象的头信息

Lock

注意:一定要把lock()放在try外面
1.如果将lock()方法放在try里面,那么try里面的代码出现异常之后,就会执行finally里的释放锁代码,但还没加锁成功
2.如果将lock()方法放在try里面,那么执行finally的释放锁代码时报的异常就会覆盖try里面的异常

synchronized锁机制是非公平锁
公平锁可以按顺序进行执行,而非公平锁执行的效率更高,是抢占式的
在Java中所有锁默认的策略都是非公平锁

不释放锁会造成死锁

synchronized使用场景:

  1. 修饰代码块(加锁对象自定义)
  2. 修饰静态方法(加锁对象是当前类对象)
  3. 修饰普通方法(加锁对象是当前类的实例)

Lock只能修饰代码块

问题:

volatile和synchronized有什么区别

volatile可以解决内存可见性问题和禁止指令重排序,但volatile不能解决原子性问题
synchronized是用来保障线程安全的,也就是说synchronized可以解决任何关于线程安全的问题(5个:抢占式执行,原子性,编译器优化,内存不可见,多个线程修改同一变量)(关键代码排队执行,始终只有一个线程会执行加锁操作)

synchronized和Lock的区别

synchronized既可以修饰代码块,和静态方法或普通方法,lock只能修饰代码块
synchronized只有非公平锁策略,而lock既可以是公平锁,也可以是非公平锁(ReentrantLock默认是非公平锁,也可以通过构造函数声明它为公平锁)
ReentrantLock更加的灵活(如:tryLock)
synchronized是自动加锁释放锁,而RenntrantLock需手动加锁释放锁

你可能感兴趣的:(笔记)