线程通信相关知识点

关于对象中的等待集(wait set)
Object.wait()
Object.notify()
Object.notifyAll()
用来做线程通信的
 
Java中每个对象:等待集
线程通信相关知识点
线程通信相关知识点
 
1.wait会使线程状态发生变化   RUNNABLE - > WAITING
                                              WAITING - > RUNNABLE
2.等的是对象的等待集上(wait是属于object的一个方法,所以等待在该对象的等待集上)
3.使用的时候必须加锁,等在哪个对象上,就对哪个对象加锁,wait执行成功时会释放锁,醒来时会重新请求锁
4.哪个线程调用wait,哪个线程进入等待集
5.notify只唤醒一个,但不保证是哪一个
 
线程通信相关知识点
线程通信相关知识点
线程通信相关知识点
 
 
 
v1和v2会cpu空转
v3条件不满足,立即出现cpu调度,但正确的线程被调度上来的机会低
v4条件不满足,立即出现cpu调度,并且指示自己不在参与调度了
 
 
线程通信相关知识点
 
线程通信相关知识点
 
1.wait和notify和notifyAll
     1.线程状态的问题
     2.加锁的问题(等在哪个对象,加哪把锁)
2.按序打印one two three
     四个版本,越来越好
3.生产者消费者模型
     1.加入线程安全
     2.提升效率
   
1.阻塞队列
2.定时器
3.线程池
 
 
定时器:
execute() {
    把任务带着时间放到一个优先级队列中(带阻塞的)
}
工作线程 {
    while(true){
         从优先级队列中取任务(可能会阻塞)
        if(task.delay如果还没到时间) {等待相应时间}
         else{去执行};
   }
}
 
线程通信相关知识点
 
 
 
线程通信相关知识点
 
 
线程通信相关知识点
 
线程通信相关知识点
 
哪些场景下,线程会放弃CPU
1.抢锁失败   =》 BLOCKED
2.wait      =》 WAITING
2.1  sleep       =》 TIME_WAITING
3.时间片到      =》 RUNNABLE
4.yield            =》 RUNNABLE
5.运行结束      =》 TERMITATE
 
状态不是RUNNABLE,必然放弃CPU,也没资格抢CPU
但是,RUNNABLE不代表就占有CPU
 
线程不安全
1.线程之间进行共享变量的操作了(读/写)
  1)哪些区域的变量是共享的
  2)哪怕有堆里的变量,如果没有线程相互操作,也不会不安全
  3)ThreadLocal
2.共享变量之间,如果只是只读,没有写,一般不需要考虑
3.原子性/可见性/重排序
 
 
机制:
  synchronized   原子性/可见性/重排序正确性
  只有发生线程调度,成本就很高(无锁编程)
  
  volatile   可见性,重排序(对象的初始化)
 
  wait/notify  加锁,过程中会释放锁(那把锁?)
 
难点:
  1.调度会发生在任意时间上的
  2.加锁是个过程:申请加锁到成功加锁,中间的间隔时间会很长,所以,申请加锁之前的很多情况都会发生变化
 
额外:
  1.死锁   广义上的(持有锁的人,停在某个环节上,不会释放锁了)
            请求其他锁/wait/死循环
   jconsole,观察每个线程的状态+调用栈
  2.锁的可重入性
    一个锁住的锁,是否允许拥有这把锁的线程重新加锁
    如果允许:具备可重入性,否则就不具备
 
    synchronized(this) {                synchronized具备
      sunchronized(this) {
   }
}
 
 
线程通信相关知识点