并发 编程


一、并发编程

  1. 线程、进程
    线程:是进程的一个执行单元,是CPU执行的最小单位;
    进程:运行中的程序是计算机分配内存资源的最小单位。

  2. 创建线程方式

    • 类 继承 Thread 重写run()
    • 实现Runnable接口 重写run() ,再创建Thread对象,去执行任务
    • 实现Callable接口,重写call()(可以有返回值,可以抛异常),再创建Thread对象,去执行任务
    • 线程池
  3. 线程常用方法
    run() yield() wait()
    start() sleep() notify()
    join()

  4. 线程的状态
    新建、就绪、运行、阻塞、死亡线程生命周期

  5. 多线程的安全问题
    多线程不一定有问题,共享操作是有问题的

  6. 解决方案
    加锁;排队;并发执行;一个一个执行

  7. 加锁方式
    synchronized关键字+同步对象(对多个线程来说是同一个对象):
    可以添加在代码上

    	synchronized(同步锁/同步对象){
    	}
    

    还可以加在方法上, 同步不需要我们提供了,静态方法,锁是类的Class对象,非静态方法,锁是this。

    ReentrantLock实现了Lock接口,所以可以称为lock锁,
    实现原理不同:
    ReentrantLock是一种java代码层面的控制实现 ,而synchronized是关键字,依靠的是底层编译后的指令实现
    加锁范围不同:
    ReentrantLock只能对某一段代码块加锁,而synchronized可以对代码块和方法加锁
    加锁释放锁方式不同:
    ReentrantLock需要手动的加锁释放锁,而synchronized是隐式的自动的加锁,自动释放锁(代码执行完了,出现异常了)

  8. 线程死锁
    指俩个或多个线程,分别持有对方需要的资源,相互僵持等待。
    死锁条件:

    • 互斥:在一段时间内某一资源仅为一个进程占用
    • 请求和保持:当进程因请求另一资源而阻塞时,对已获得的资源保持不放
    • 不可抢占:进程已获得的资源在未使用完之前,不可被抢占,只能在使用完时由自己释放
    • 循环等待:存在一个进程请求资源的循环链
      措施:
    • 预防死锁:设置某些限制条件破坏死锁的几个必要条件
    • 避免死锁:在资源的动态分配中,用某种方法防止系统进入不安全状态
    • 检测死锁: 允许程序出现死锁,出现后及时检测然后采取措施,将进程从死锁中解脱出来
    • 解除死锁: 当检测到死锁发生时,可以撤销一些进程,回收它们的资源.
  9. 线程通信
    同步情况下 、notify()、wait()

二、线程进阶

围绕着线程安全问题,用户在手机上买票,抢购,秒杀

a.多线程

优点:提高程序的响应速度,可以多个线程完成自己的工作,提高硬件设备的利用率
缺点:可能会出现资源争夺问题
并发执行:在一段时间内,多个线程依次执行
并行执行:真正意义上的同时执行,俩个线程在同一个时间点上一起执行
高并发指的是很多用户一起访问

b.并发编程核心问题

不可见性:一个线程对共享变量的修改,另外一个线程不能够立刻看到
由于想让程序响应处理速度更快, java内存模型设计有主内存和工作内存(线程使用的内存)。线程中不能直接对主内存中的数据进行操作,必须将主内存数据加载到工作内存(本地内存), 这样在多核cpu下就会产生不可见性。

乱序性:指令在执行过程中,为了优化性能,可能将一些语句的顺序改变。
volatile
可以解决不可见性, volatile修饰的变量在一个线程修改后,对其他线程立即可见,还可以解决乱序性, volatile修饰的变量在执行时禁止指令重排序,但是不能解决非原子性问题

非原子性:线程切换带来的非原子性问题,A先执行被B插了一脚。
原子性:一个或多个操作在 CPU 执行的过程中不被中断的特性
措施:

  1. 加锁:互斥的,A线程执行时加锁,此时其他线程就不能执行了。
  2. 原子变量(解决++之类的问题)
    在java.util.concurrent包下面提供一些类,可以在不加锁的情况下,实现++操作的原子性,这些类称为原子类AtomicInteger,原子类内部实现是 volatile+CAS机制
    CAS机制:比较与交换,乐观锁(不加锁)实现,采用自旋思想(一个循环中不断地尝试更新操作,直到成功或者放弃)
    包含三个操作数:内存值、预估值、更新值,判断预估值和主内存中的值是否一致,如果一致说明没有其他线程修改过, 如果不一致说明其他线程修改过。重新获取主内存的共享变量,重复操作。
    CAS缺点:原子类内部实现使用了不加锁的CAS机制,线程不会被阻塞,所有的线程都会不断的重试进行操作,在访问量大的情况下,会导致cpu消耗过高,原子类适合在低并发情况下使用。
    ABA问题:一个线程读取一个共享变量的值为A,然后另一个线程将该值修改为B,再改回A。此时,线程再次尝试进行CAS操作时,会发现该变量的值仍然是A,因此它会认为该值没有被修改过。
    解决ABA问题:使用有版本号的原子类

c.Java中的锁分类

  1. 乐观锁/悲观锁
    乐观锁:不加锁,乐观锁认为不加锁的并发操作是没有问题的,并发修改时进行比较,满足条件进行更
  • 26
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值