并发安全问题探究

目录

1. 线程安全性

1.1 什么是线程安全性

1.2 如何实现线程安全性

1.2.1  线程封闭

1.2.2 栈封闭

1.2.3 TheadLocal

1.2.4 无状态的类

1.2.5 让类不可变

1.2.6 加锁和 CAS

2. 死锁

2.1 什么是死锁

2.2 如何解决死锁

3. 活锁

4. 线程饥饿


1. 线程安全性

1.1 什么是线程安全性

        我们所写的代码在并发情况下使用 时,总是能表现出正确的行为;反之,未实现线程安全的代码,表现的行为是不 可预知的,有可能正确,而绝大多数的情况下是错误的。

1.2 如何实现线程安全性

        如果要实现线程安全性,就要保证我们的类是线程安全的。在《Java 并发编程实战》中,定义“类是线程安全的”如下:当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在调用代码中不需要任何额外的同步或者协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的。

1.2.1  线程封闭

        就是把对象封装到一个线程里,只有这一个线程能看到此对象。那么这个对 象就算不是线程安全的也不会出现任何安全问题。

1.2.2 栈封闭

        栈封闭是我们编程当中遇到的最多的线程封闭。什么是栈封闭呢?简单的说 就是局部变量。多个线程访问一个方法,此方法中的局部变量都会被拷贝一份到线程栈中。所以局部变量是不被多个线程所共享的,也就不会出现并发问题。所 以能用局部变量就别用全局的变量,全局变量容易引起并发问题。

1.2.3 TheadLocal

        ThreadLocal 是实现线程封闭的最好方法。 ThreadLocal 内部维护了一个 Map , Map 的 key 是每个线程的名称,而 Map 的值就是我们要封闭的对象。每个线程 中的对象都对应着 Map 中一个值,也就是 ThreadLocal 利用 Map 实现了对象的 线程封闭。

1.2.4 无状态的类

        没有任何成员变量的类,就叫无状态的类,这种类一定是线程安全的。

1.2.5 让类不可变

        让状态不可变,加 final 关键字,对于一个类,所有的成员变量应该是私有 的,同样的只要有可能,所有的成员变量应该加上 final 关键字,但是加上 final ,要注意如果成员变量又是一个对象时,这个对象所对应的类也要是不可变,才能 保证整个类是不可变的。
        注意:一旦类的成员变量中有对象,上述的 final 关键字保证不可变 并不能保证类的安全性,为何?因为在多线程下,虽然对象的引用不可变,但是 对象在堆上的实例是有可能被多个线程同时修改的,没有正确处理的情况下,对象实例在堆中的数据是不可预知的。

1.2.6 加锁和 CAS

        我们最常使用的保证线程安全的手段,使用 synchronized 关键字,使用显式 锁,使用各种原子变量,修改数据时使用 CAS 机制等等。

2. 死锁

2.1 什么是死锁

        是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信 而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁。
可以总结为:
1、死锁是必然发生在多操作者(M>=2 个)争夺多个资源(N>=2 个,且 N<=M)才会发生这种情况。很明显,单线程自然不会有死锁。
2、争夺资源的顺序不对,如果争夺资源的顺序是一样的,也不会产生死锁;
3、争夺者对拿到的资源不放手。

2.2 如何解决死锁

第一步 定位: 通过 jps 查询应用的 id,再通过 jstack id 查看应用的锁的持有情况。
第二步 修正: 关键是保证拿锁的顺序一致
两种解决方式
1、内部通过顺序比较,确定拿锁的顺序;
2、采用尝试拿锁的机制。

3. 活锁

        两个线程在尝试拿锁的机制中,发生多个线程之间互相谦让,不断发生同一 个线程总是拿到同一把锁,在尝试拿另一把锁时因为拿不到,而将本来已经持有的锁释放的过程。死锁时程序卡顿,时block状态,活锁是runable状态。
解决办法:每个线程休眠随机数,错开拿锁的时间。

4. 线程饥饿

        低优先级的线程,总是拿不到执行时间

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瑜伽娃娃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值