android如何保证多线程安全,保证线程安全的方式有哪几种?

欢迎关注我的公众号:

![我的公众号](https://markdown-1258186581.cos.ap-shanghai.myqcloud.com/20190606104746.png)

## 什么是线程安全?

![](https://markdown-1258186581.cos.ap-shanghai.myqcloud.com/20190610101014.png)

## volatile 关键字

保证了有序性,可见性,但是没保证原子性。

由于java的内存模型的原因,线程在修改了共享变量后并不会立即把修改同步到内存中,而是会保存到线程的本地缓存中。

**volatile关键字修饰的变量在线程修改后会立刻同步到主内存中,使该修改对其他线程可见**

## Synchronized 关键字

* sychronized 是java中的内置锁,可以限制线程对代码块或者方法的访问

* sychronized可以修饰类方法,实例方法,代码块

* 在执行sychronized方法或代码块时,线程需要先获取被修饰对象的锁。一次只能有一个线程可以获取到一个对象的锁,同一个线程可以多次获取同一个对象的锁(可重入锁)

* sychronized 不能响应中断,当一个线程在等待锁的时候,调用该线程的interrupt是不起作用的

* 锁的获取和释放是隐式的,进入同步sychronized blocks后会获取锁,离开sychronized blocks后会释放锁

## Obejct类的wait/notify方法

* wait/notify是用于线程同步的方法

* wait方法会使得当前线程放弃调用对象的监控,并使当前线程进入等待。直到调用了该对象的notify方法或者notifyAll方法(语法上是这样设计,但存在例外)

* 可以多次调用对象的wait方法,notify方法只会随机释放一个wait方法等待,与调用顺序无关。如果要释放所有的wait调用可以调用notifyAll方法

* 调用wait的线程有可能会存在interrupt,虚假唤醒的情况,导致wait方法返回,但实际并没有调用对象的notify方法。在使用时通常会搭配一个lock flag和loop使用

## ThreadLocal 实现

ThreadLocal实例通常作为静态的私有的(private static)字段出现在一个类中,这个类用来关联一个线程。ThreadLocal是一个线程级别的局部变量,下面是线程局部变量(ThreadLocal variables)的关键点:

1. 当使用ThreadLocal维护变量时,若多个线程访问ThreadLocal实例,ThreadLocal为每个使用该变量的线程提供了一个独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其他线程所对应的副本。

2. 从线程的角度看,目标变量就像是线程的本地变量,这也是类名中Local所要表达的意思。

首先:ThreadLocal 是一个泛型类,内部有个静态内部类 ThreadLocalMap,使用弱引用的方式保存 ThreadLocal。

在每个线程内部有一个`ThreadLocal.ThreadLocalMap threadLocals = null;`, 这个 map 的 key 就是每个线程的实例.

在 get 或者 put 的时候,会先通过 getMap 拿当前线程绑定的 ThreadLocalMap 对象,如果没有,会创建一个新的对象。以 ThreadLocal 为 key,以泛型为 value。

这样,在访问 ThreadLocal 类的时候,都会通过拿其内部的 ThreadLocalMap,然后再去获得设置的泛型值。

所以就导致,不同的类在内部设置 ThreadLocalMap 以后,确保能够保证同个线程中值是唯一的。

[参考地址](https://www.cnblogs.com/studyLog-share/p/5295557.html)

## 重入锁实现线程同步

Lock,一般使用其实现类 ReentrantLock。

ReentrantLock获取锁定与三种方式:

1. lock(), 如果获取了锁立即返回,如果别的线程持有锁,当前线程则一直处于休眠状态,直到获取锁

2. tryLock(), 如果获取了锁立即返回true,如果别的线程正持有锁,立即返回false;

3. tryLock(long timeout,TimeUnit unit), 如果获取了锁定立即返回true,如果别的线程正持有锁,会等待参数给定的时间,在等待的过程中,如果获取了锁定,就返回true,如果等待超时,返回false;

4. lockInterruptibly:如果获取了锁定立即返回,如果没有获取锁定,当前线程处于休眠状态,直到或者锁定,或者当前线程被别的线程中断

ReentrantLock 和 Synchronized 的区别:

线程A和B都要获取对象O的锁定,假设A获取了对象O锁,B将等待A释放对O的锁定,

- 如果使用 synchronized ,如果A不释放,B将一直等下去,不能被中断

- 如果 使用ReentrantLock,如果A不释放,可以使B在等待了足够长的时间以后,中断等待,而干别的事情

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值