并发编程-线程安全

1. 什么是线程安全

在多线程访问下, 不管哪个线程调用这个类,这个类总能表现出正确的行为

JMM 引发的问题

在这里插入图片描述

  1. 数据不一致, 缓存不一致
  2. 指令的重排序

怎样才能做到线程安全

1. 无状态类(没有成员变量的类)
public class A{
public void proc(int a, int b){

}
}

2. 让类不可变

public class A{
private final int x=0;// 安全的
private final user u = new user();//user 类里面与变量, 不能防止其他程序修改这个变量。是不安全的. 除非a也是final 的
public void proc(int a, int b){

}
class user{
int a;
}
}

  1. volatile
  2. 枷锁
  3. CAS
  4. 。。。。

线程不安全

  1. 死锁: 是指两个或者两个以上进程在执行过程中, 由于竞争资源, 或者由于彼此通信, 而造成的一种阻塞现象, 若无外力作用,他们都将无法推进下去, 此时称系统处于死锁状态或系统产生了死锁
    简单的死锁:
    代码示例:
    在这里插入图片描述
    在这里插入图片描述

A 线程拿到了1 资源, B线程拿到了2 资源, 但是A 也需要拿到2 资源才可以执行,B 需要拿到1 才能执行, 此时, 1被A 占着, 2 被B 占着, A 拿不到2 , B 拿不到1 。所以A和B 就死锁了

解决:两个线程同时拿1锁, 再拿2 锁
解决示例:
在这里插入图片描述
在这里插入图片描述

动态死锁
A 账户转给B 账户钱
先锁转出, 再锁转入

线程1 :张三转给李四
线程2:李四转给张三

则转入 和转出的账户, 是参数形式, 不固定
在这里插入图片描述
在这里插入图片描述
不安全操作
在这里插入图片描述

解决办法:使 在java system 类里面有个 identifyHashCode 对传入的参数进行排序, 先锁小的, 再锁大的, 出现hash碰撞后(算出的hashcoe 值一样), 可以进行加时处理使线程再重新跑一次

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

其他死锁:资源争夺 也会产生死锁

活锁:

显示锁Lock, 里面的tryLock() 尝试去拿锁, 拿不到时, 会释放这个说
线程A, 拿到锁1 后, 尝试拿锁2 , 线程B 哪到锁2 后尝试拿锁1, 1 和2 豆被线程占着, 所以线程A 会释放尝试拿2 的锁, 线程B 会释放拿1 的锁。 之后再尝试去拿, 线程在不断的尝试拿锁, 释放锁的过程。 此时线程A 和B 一直在运行, 但是此时运行时无效的

线程饥饿

:与线程优先级有关, 优先级高的线程总是会占有cpu, 优先级第的总是拿不到cpu 的使用权, 则优先级第的线程处于线程饥饿状态

提高性能

多线程代用calc 这个方法, 当a , b 数特别特别大的时候, 计算需要时间, 则, 调用这个方法的线程豆需要等待这个计算结果才能执行

在这里插入图片描述

优化后:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_41572697/article/details/89366994