深入理解java中的线程并发(学习笔记一)

线程的状态

在java中
线程的启动方式只有两种:

  1. Thread.start
  2. 创建一个Runnable任务交给Thread运行

线程的状态分为6种:

  1. 初始状态:新创建了一个Thread,但还没有start
  2. 运行状态:在java中ready和running两种状态都称为运行
  3. 阻塞:表示线程阻塞于锁
  4. 等待:等待其他线程做出一些特定动作(中断,通知)
  5. 超时等待:与等待不同,在指定时间自行返回
  6. 终止:表示执行完毕

状态流程图

死锁

发生死锁,有四个必要条件:

  1. 互斥:进程对所分配的资源进行排他性使用,其他进程申请该资源只能等待占有资源的进程执行完毕。
  2. 请求和条件保持:已经占有了至少一个资源,又提出新的资源请求,而该资源已被其他进程占有,此时请求被阻塞,但对自己占有的资源不释放
  3. 不剥夺:进程占有的资源未使用完之前不能被剥夺,只能自己使用完成时释放
  4. 环路等待:对资源的需求形成环形链

要避免和预防、解决死锁,只需要破坏以上四个条件之一就可以:

  1. 打破互斥:改造独占资源为虚拟资源(大部分资源无法改造)
  2. 打破占有且申请:资源预先分配,运行前申请全部资源,不满足就等待
  3. 打破不可抢占条件:获取另一个资源失败时,释放原来占有的资源
  4. 打破循环等待:实现一种分配策略,按序申请资源

保证拿锁顺序一致性:
1.内部比较顺序
2.尝试拿锁机制(会导致活锁:互相谦让,不同线程总是拿同样的锁,解决办法是给一个很短的随机的休眠时间,错开拿锁)

ThreadLocal

ThreadLocal通过为每一个线程创建一个独立的变量副本,来解决并发访问的冲突问题,与同是解决多线程并发访问的synchonized相比有着本质的区别,synchonized是利用锁的机制,使变量或代码块在同一时刻仅能被一个线程访问。

每个线程内部有一个ThreadLocal.ThreadLocakMap类型成员变量threadLocals,这个threadLocals就是用来存储实际变量副本的,当调用get或set方法时,会将为空的threadLocals初始化,以当前的ThreadLocal为key,以ThreadLocal要保存的变量副本为value,存到threadLocals中,所以即使是同一个ThreadLocal变量引用,也无法访问另一个线程的ThreadLocal变量

  1. 实际通过ThreadLocal创建的副本是存在每个线程自己的threadlocals中的
  2. 每个线程可以有多个threadlocal变量
  3. 在进行get之前,必须先set,否则会空指针异常,或者重写initialVlaue()方法,默认会返回一个null

在Android的Handle源码中,由于每个线程的looper是不一致的,内部就通过使用ThreadLocal存储和获取自己的Looper对象。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值