Java—多线程小结

线程状态转移

在这里插入图片描述

状态转移注意点

  1. 线程调度会发生在任意时间上。
  2. 加锁是个过程:申请加锁到枷锁成功,中间间隔时间会很长。所以,申请加锁之前的很多情况会发生变化
  3. 只有在线程状态是RUNNABLE时,才可以资格竞争CPU,才可以抢锁。
  4. 状态不是RUNNABLE,必然会放弃CPU,也没资格抢CPU;但是,状态时RUNNABLE,不代表一定可以占有CPU
  5. 那些场景线程会放弃CPU?
放弃CPU的场景 当前状态
抢锁失败 BLOCKED
wait() WAITING
sleep(long) TIMED_WAUTING
时间片到了 RUNNABLE,进入就绪队列
yeild RUNNABLE,进入就绪队列
运行结束 TERMINATED

线程不安全

  1. 线程之间进行了共享变量的操作(读/写)
    1>除了栈,其他区域里的都是共享的。
    2>共享不一定就是不安全的(如果没有线程之间相互操作,也不会不安全)。
    3>ThreadLocal线程安全(给每个线程划分自己的空间)。
  2. 共享变量只读(不写),一般不考虑线程安全问题。
  3. 原子性/可见性/重排序

强调:机制

  1. synchronized:原子性/可见性/重排序正确性
    注意:主要发生进程调度,成本就很高(尽可能设计无锁队列)
  2. volatile 可见性、重排序(对象的初始化)
  3. wait / notify:使用前加锁、过程会释放锁(释放wait对象的那把锁)

死锁、活锁

  1. 死锁
    1> 定义:广义上的(持有锁的人,停在某个环节,不会释放锁)。
    eg:请求其他锁/wait/死循环
    2> 注意:出现死锁,可用 jconsole,观察每个线程的状态+调用栈
  2. 锁的可重入性
    理解:一个锁住的锁,是否允许拥有这把锁的进程?(如果允许,具有可重入性;否则不具有)
    eg:synchronized具有锁的可重入性。
synchronized (this){
            synchronized (this){
                
            }
        }
发布了71 篇原创文章 · 获赞 3 · 访问量 1248

猜你喜欢

转载自blog.csdn.net/qq_43361209/article/details/103099161