Android笔记(十七)Android多线程问题

参考 https://mp.weixin.qq.com/s/gBZcogHizremZoJRvd8fHQ

线程的几个方法

  1. run()。非静态
  2. start()。非静态
  3. join()。非静态。如果线程 A 调用了线程 B 的 join() 方法,那线程 A 会进入等待状态,直到线程 B 运行结束。
  4. currentThread()。静态
  5. yield()。静态。降低当前线程优先级,调用该方法就像是是对线程调度器说:“如果其他线程要处理器资源,那就给它们,否则我继续用”。
  6. sleep()。静态

线程的生命周期

Android笔记(十七)Android多线程问题_第1张图片

JVM内存模型

Android笔记(十七)Android多线程问题_第2张图片
JAVA运行时的数据区域可以包括:
方法区。方法区存放类的信息(包括类的字节码,类的结构)、常量、静态变量等。字符串常量池就是在方法区中。
堆区。主要存放数组和对象,包括持久代,年老代,初生代等
虚拟机栈。线程独占。存放局部变量表(基础数据和引用)
本地方法栈。线程独占。存放native相关
程序计数器(线程寄存器)。线程独占。保存线程执行指令

JAVA内存模型

Android笔记(十七)Android多线程问题_第3张图片
这幅图是区分于JVM内存模式。后者是从功能上区分内存模型,前者是从架构考虑,高速cache的存在是为了加速数据读写,而不同线程之间对内存的读写就涉及到了多线程并发工作的问题,从而产生了竞态这一说法。

线程安全性问题(竞态)

  1. 原子性。操作不可分割。其他线程不会参与
  2. 可见性。某一线程改变共享变量后需要同步到其他线程
  3. 有序性。保证操作的有序性。重排序(Reordering)处理器和编译器是对代码做的一种优化,它可以在不影响单线程程序正确性的情况下提升程序的性能,但是它会对多线程程序的正确性产生影响,导致线程安全问题。

实现线程安全(锁)

要实现线程安全就需要保证上面的三点。常见的实现线程安全的办法是使用锁和原子类型,而锁可分为内部锁(synchronized)、显式锁、读写锁、轻量级锁(volatile)四种

  • 内部锁(synchronized)。同步方法或者代码块,锁住特定类和特定对象。因为使用 synchronized 实现的线程同步是通过监视器(monitor)来实现的,所以内部锁也叫监视器锁。不需要手动释放锁如(unlock),可以自动解锁非公平锁
  • 显示锁,实现了Lock接口。可重入,锁多次;需要手动获取和释放,允许调整锁策略成功公平/非公平锁。
  • 读写锁
  • volatile 关键字
  • Android笔记(十七)Android多线程问题_第4张图片
    读线程执行的加载屏障和写线程执行的存储屏障配合在一起,能让写线程对 volatile 变量的写操作对读线程可见,从而保证了可见性;volatile 能禁止指令重排序,也就是使用 volatile 能保证操作的有序性;在原子性方面,对于 long/double 型变量,volatile 能保证读写操作的原子型
    对于非 long/double 型变量,volatile 只能保证写操作的原子性。

死锁 4 个必要条件

  • 互斥
  • 占有且等待
  • 不可抢占
  • 循环等待

你可能感兴趣的:(andorid)