java多线程与并发编程1

创建线程的3种方式
第一种:继承Thread类,重写run()方法
第二种:实现Runnable接口,重写run()方法
第三种:实现Callable接口,重写run()方法

线程生命周期
1.new新建状态
2.runnable可运行状态
        包括:1.ready就绪状态,线程调用start()方法之后,等待jvm的调度
              比如:yield()线程让步
                2.running运行状态,线程对象得到jvm的调度
3.blocked阻塞状态
4.waiting等待状态
             注:调用wait()调用wait会释放掉锁,而sleep不会,join()等方法就会进入等待状态
           wait()方法处于等待的线程通过调用notify()和notifyall()方法唤醒等待中的线程
          join()是线程插队,调用join的线程会先执行,其他线程等到执行完了才能执行
5.Timed_Waiting定时等待状态,比如sleep()线程睡眠
6.terminated终止状态

重点:线程安全
CPU的三级缓存:每个CPU都有L1,L2,L3三级缓存
CPU查找数据的顺序为CPU->L1->L2->L3->内存->硬盘
L1,L2是cpu中同一核内共享数据
L3是cpu中不同核中共享数据
内存中的缓存行是CPU间共享数据

重点
java中,一切不可变的对象一定是线程安全的!比如,final关键字修饰的对象。

互斥同步:synchronized是java中最基本的互斥同步手段,互斥同步会让没抢到锁的线程挂起,等到能执行时在唤醒,挂起和唤醒过程会非常的耗开销。互斥同步也叫阻塞同步!是一种悲观的并发策略!

非阻塞同步:是基于冲突检测的乐观并发策略,没抢到锁时会再次进行抢锁,成功则成功,没成功会一直自旋!

线程竞争激烈时,悲观并发策略适合,竞争不激烈时,乐观并发策略适合

synchronized的原理(锁升级)
对象头主要包括2部分(mark word标记字段   kiass pointer 类型指针)
标记字段01为无锁态
00为轻量锁    没抢到锁的线程会自旋
10为重量锁(互斥锁)    没抢到锁的线程会挂起

死锁
java产生死锁的4个条件
1.互斥使用
2.不可抢占
3.请求和保持(请求其他资源的时候,保持原有资源的占有)
4.循环等待
解决死锁问题的方法是:synchronized同步代码快和lock显式锁
线程重入:线程获取到锁后,再次获取该锁不会被该锁阻塞!

Lock锁(显式锁)
lock是获取锁,unlock释放锁

Lock lock = ...;
lock.lock();
try{
    //处理任务
}catch(Exception ex){

}finally{
    lock.unlock();   //释放锁
}


java并发编程的3大特性
原子性 : 在某一时刻,一进程不能分开被线程执行,只能由一个线程执行到底
可见性:线程和线程之间的数据是否可见(可见会带来一系列安全问题)
有序性:指令乱序重排序的问题(乱序重排序也会带来数据不一致问题)
volatile可以保证可见性和有序性
synchronized和lock可以保证原子性,可见性和有序性

lock锁的原理(Cas  Aqs)

cas
cas的思路其实很简单,就是给一个元素赋值的时候,先看看内存里的那个值到底变没变,如果没变我就修改,变了我就不改了,其实这是一种无锁操作,不需要挂起线程,无锁的思路就是先尝试,如果失败了,进行补偿,也就是你可以继续尝试。这样在少量竞争的情况下能很大程度提升性能。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzUzMjUyNzE1,size_20,color_FFFFFF,t_70,g_se,x_16

重点:Cas是通过比较期望值和原值,不一致会再次尝试,进行自旋。这样在少量竞争的情况下能很大程度提升性能Cas保证的是对一个对象写操作的无锁原子性。加syncronized的也具有原子性。

CAS还是有几个缺点
1.ABA问题。当第一个线程执行CAS操作,尚未修改为新值之前,内存中的值已经被其他线程连续修改了两次,使得变量值经历 A -> B -> A的过程。绝大部分场景我们对ABA不敏感。解决方案:添加版本号作为标识,每次修改变量值时,对应增加版本号; 做CAS操作前需要校验版本号。JDK1.5之后,新增AtomicStampedReference类来处理这种情况。
2.循环时间长开销大。如果有很多个线程并发(高并发时),CAS自旋可能会长时间不成功,会增大CPU的执行开销。
3.只能对一个变量进行原子操作。JDK1.5之后,新增AtomicReference类来处理这种情况,可以将多个变量放到一个对象中。

Aqs见下篇

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

奥特曼的一号蛋

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

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

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

打赏作者

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

抵扣说明:

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

余额充值