线程
2020-03-17 18:07:38 0 举报
登录查看完整内容
java线程知识点
作者其他创作
大纲/内容
状态state (enum)
threadlocalmap类static class ThreadLocalMap
waiting
线程A继续持有锁
线程A
实现runnabepublic class ThreadTest implements Runnable{public void run(){}}
属性
voliate 保证共享变量的可见性
cpu的时间片用完,暂时需要交出cpu
工作内存flag=false;flag=true
检测冲突
同步代码块阻塞/io阻塞
死锁:a线程持有锁A ,同时b线程持有锁B,但是a线程需要获取锁B才能进行下去,b线程 需要获取锁A才能进行下去,这样就产生了死锁。jstack命令可以发现死锁,也可以使用lock显式锁或是带有超时时间的锁进行加锁
并行一个新的线程执行
持有锁的线程结束,释放锁,唤醒所有阻塞的线程,重新竞争锁
弱引用
否
释放锁
public static native void yield();调用改方法会告诉系统调度器,该线程不着急占用cpu,可以先让其他线程执行,但是具体的执行还需要看调度器的结果
升级为重量级锁,所有竞争锁的线程都处于阻塞状态,减少自旋带来的CPU空转
Map:threadLocalsMap
main
key
value
自旋次数(默认10次)到了,或是子线程A自旋的过程中,有其他线程进来竞争锁
name
ReentrantReadWriteLock 实现类
线程1
获取不到锁
主动休眠 sleep方法
将线程放入条件等待队列(对象的等待队列有两个:一个是锁竞争的等待队列,另一个是存放在等待某些条件触发的线程的队列也叫条件队列)
public static native Thread currentThread();获取当前的线程
thread
初始化flag=false;
监听线程1修改以后flag修改为true;
进行锁竞争
执行完毕/异常中断
ABA问题假设当前的值为A ,然后另一个线程吧值从A修改为B有修改为A,这样当前线程是cas是无法分辨值是否改变过。如果遇到该问题可以使用atomicstampereference,该类在修改值的时候同时会附加一个时间戳,只有值和时间戳同时相同的 时候哦才会修改值
有冲突
进入等待队列知道获取到锁以后执行完成
notify()
执行的cpu1
是
voliate缓存可见性实现原理:底层实现主要是通过汇编lock前缀指令,它会锁定这块区域内的缓存(缓存行锁定)并会回写到主内存。IA-32架构开发者对lock指令的解释:1)会将当前处理器缓存行的数据立即写会系统主存2)这个写回内存的操作会引起在其他cpu里缓存了该内存地址的数据无效(MES协议)
ReadWriteLock(接口)
工作内存flag=false;
ReentrantLock
可重入性:对同一执行的线程,他在获得了所以后,还可以继续调用其他需要同样的所得代码块或是方法。实现方式:通过记录锁持有的线程和持有数量来实现,当调用了synchronized修饰的代码时,需要检查对象是否被锁了,如果被锁了再检查是否是呗当前的线程锁定的,如果是贼增加持有的数量,如果不是被当前线程锁定,则放入等待队列,等待锁释放。如果 获取了锁,当锁被释放的时候就会减少持有数量,当持有数量变为0的时候,整个锁才会被释放
优先级priority(1-10 默认5)
ReentrantLock 实现类
锁升级过程
执行完成
线程
new SoftReference<>
不存活
new object ()
将markword中的threadid换成线程A的threadid
主内存
休眠期限到期
线程A继续自选等待
public static native void sleep(long millis) throws InterruptedException;
睡眠期间线程会让出cpu,具体的睡眠时间并不会严格的按照参数给定的毫秒数,会有偏差,偏差与系统的定时器和操作系统的准确度和精度有关,睡眠期间线程可以被中断,并抛出interruptedExcepti
获取新值
wait方法流程
blocked
public final void join() throw InterruptedException
等待(waiting或是timed_waiting)
CAS(compareAndSet)lock cmpxchg指令
线程2
store 修改完成以后,主内存通过嗅探监听机制,立即从线程1的工作内存读取修改后的值,然后线程2的值失效
可以让调用join的线程等待改线程结束
timed_waiting
tl
thread类ThreadLocal.ThreadLocalMap threadLocals = null;
修饰代码块:synchronized(object){}
调用wait
public final boolean isDaemon();线程是否为守护线程
集成Threadpublic class ThreadTest extends Thread{public void run(){}}
无冲突
方法
执行的cpu2
running
对象头markword中的threadid是否跟线程A的一样
判断持有偏向锁的线程是否存活
;notify()唤醒的是等待队列的第一个线程,notifyall()唤醒的是等待队列的所有线程
等待被打断,notify
更新
显式锁
1.load线程1从主内存读取flag=false
new Thread().run()
id
同步代码块释放锁/IO资源释放
能获取到锁
分配资源
竞争锁
等待时间到了或是被notify唤醒,其实就是从那条件队列移除
线程2从修改以后的主内从读取新的flag值
暂停持有锁的线程,然后将markword的锁标志位改为00(轻量级锁),然后线程A自旋等待锁释放
public final native boolean isAlive();线程是否存活
synchronized 等待锁的过程中不能 响应中断 monitorenter和monitorexit
new Thread().start()
Lock(接口)
存活
判断是否为偏向锁
加锁的对象对象头的markword的最后两位是锁标志位,倒数第三位是偏向锁标志位
threadlocal set()
修饰类的实例方法:public synchronized void function(){}synchronized修饰实例方法保护的是同一个对象的方法调用,其实它保护的就是这个当前的实力对象,如果类里面还有另一个方法被synchronized修饰,则这两个方法不能被同时调用
threadLocal tl=new ThreadLocal();new Thread(){tl.set(obj);tl.remove();}
修饰类的静态方法:public synchronized static void function(){}synchronized保护的就是这个 类对象既:XXX.class
public final void setDaemon();设置当前线程为守护线程
1.load线程2第一次读取flag=false;
so
RUNNABLE
dead
每个线程都会有一个threadlocalmap,每个threadlocalmap的一对k-v就是个一个entry,这个entry的类是继承的weakreference,所以他是一个弱引用,好处在于当tl的强引用不存在以后,就会被回收,但是当key被回收以后,value的值就没办法在访问到,导致无法被回收,最终导致内存泄露的风险。所以在tl使用完了以后要调用一下tl.remove();
entry类static entry extends weakreference
线程执行完毕,再继续执行主线程的代码
主动等待,调用wait()方法
CPU总线MESI缓存一致性协议
内存可见性;synchronized在释放锁的时候所有写入操作都会写回内存,获取锁以后,还会读取内存最新的数据
new Thread()
线程状态循环图
threadlocal类
NEW
LockSupportpublic static void park();使当前线程放弃cpu进入waiting状态,直到其他线程对她使用了unpark方法,当前线程才可以进入运行状态public static void unpark(Thread thread);public static void parkNanos(long nanos)可以指定等待的最长时间public static void parkUntil(long deadlines)可以指定最长等待到什么时候(相对纪元的毫秒数)
new ThreadLocal()
0 条评论
回复 删除
下一页