Java并发总结

Java并发总结

一.多线程并发编程
1、如何控制线程执行顺序

  1.1、通过join()方法,让主线程等待子线程结束以后才能继续进行

  1.2、通过Executors.newSingleThreadExecutor()这个线程池,因为它有FIFO机制

2、lock和synchronized区别

  2.1、synchronized锁什么时候释放

    a.获取锁的线程执行完了改代码块

    b.线程执行出现异常

  2.2、Lock可以主动去释放锁,synchronized是被动的

    lock锁可以被中断,尝试获取锁,超时获取锁

    如果在绝对时间上,先对锁进行获取的请求你一定先被满足,那么这个锁是公平的,反之,是不公平的。公平锁的获取,也就是等待时间最长的线程最优先获取锁。

    非公平锁的效率更高

  2.3、ReentrantLock和synchronized关键字,都是排它锁

3、为什么弃用stop和suspend方法

  3.1、stop方法天生不安全,当线程被终止,立即释放被它锁住的所有对象的锁,会导致对象处于不一致状态。

  3.2、suspend方法经常会导致死锁,suspend挂起一个持有锁的线程,那么,在该锁恢复之前是不可用的,如果调用suspend的方法线程试图获得同一个锁,那么程序死锁,被挂起的线程等着被恢复,而将其挂起的线程等待获得锁。

4. sleep() 和 wait() 有什么区别?

 sleep 就是正在执行的线程主动让出 cpu,cpu 去执行其他线程,在 sleep 指定的时间过后,cpu 才会回到这个线程上继续往下执行,如果当前线程进入了同步锁,sleep 方法并不会释放锁,即使当前线程使用 sleep 方法让出了 cpu,但其他被同步锁挡住了的线程也无法得到执行。wait 是指在一个已经进入了同步锁的线程内,让自己暂时让出同步锁,以便其他正在等待此锁的线程可以得到同步锁并运行,只有其他线程调用了 notify 方法(notify 并不释放锁,只是告诉调用过 wait 方法的线程可以去参与获得锁的竞争了,但不是马上得到锁,因为锁还在别人手里,别人还没释放。如果 notify方法后面的代码还有很多,需要这些代码执行完后才会释放锁,可以在 notfiy 方法后增加一个等待和一些代码,看看效果),调用 wait 方法的线程就会解除 wait 状态和程序可以再次得到锁后继续向下运行。

二、volatile和synchronized区别
1 、JMM(Iava内存模型):并发过程中如何处理可见性,原子性,有序性的问题。

并发过程中的两个关键问题

1.1、线程之间如何通信,wait() notify() notifyall()

    共享内存----->显式通信

    消息传递----->隐式通信

1.2、线程之间如何同步

    在共享内存的并发模型中,同步是显式做的,synchronized

    在消息传递的并发模型中,由于消息的发送必须在消息接收之前,所以同步是隐式

2、定位内存可见性问题,什么对象是内存共享的,什么不是
3、对于声明了volatile的变量进行写操作的时候,JVM会向处理器发送一条Lock前缀的指令,会把这个变量所在缓存的数据写到回到系统内存。在多处理器的情况下,保证各个 处理器缓存一致性特点,就会实现缓存一致性协议。
4、synchronized:可重入锁、保证了互斥性、可见性, JVM内置锁通过synchronized使用,通过内部对象Monitor(监视器锁)实现,基于进入与退出Monitor对象实现方法与代码块同步,监视器的锁依赖于底层操作系统的Mutex lOCK(互斥锁)实现,它是一个重量级锁,性能较低,
5、认识对象的内存结构:

  5.1、 对象头:比如hash码,对象所属的年代,对象锁,锁状态标志,偏向锁,偏向时间,数组长度等

  5.2、对象实际数据:即创建对象时,对象中成员变量,方法等

  5.3、对齐填充:对象的大小必须是8字节的整数倍

  /5.4JDK1.6版本之后对synchronized的实现进行了各种优化,如适应性自旋锁,轻量级锁,偏向锁,并默认开启偏向锁
无锁---->偏向锁---->轻量级锁---->重量级锁

6、volatile: 可以做到可见性、不能做到原子性
三、锁的概念
1、死锁:指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象。
   查看死锁:jps -m     jstack 进程号
2、行锁,页锁,表锁:在mysql中,在sql语句末尾加for update

  2.1、读锁:在mysql中,加lock in SHARE MODE

  2.2、写锁:加for update

  2.3、悲观锁:对数据被外界修改保持悲观态度,在数据处理过程中,将数据处于锁定状态,往往依靠数据库的锁机制实现

  2.4、乐观锁:假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做或者让程序自动去重试。

  2.5、乐观锁只是在更新数据的那一刻锁表

    (1)通过版本号实现:update t_goods_info set amout = amout-#{buys},version = version+1 where code = #{code} and version = #{version}
        
    (2)通过状态为控制update t_goods_info set amout = amout - #{buys} where code = #{code} and amout - #{buys} >= 0
         
    (3)基于redis的实现:利用watch指令在redis事务中提供CAS的能力
         
    (4)基于memcaches的实现,通过get和cas实现
3、什么是原子操作?如何实现

  CAS的原理(compare and swap):利用了现代处理器都支持CAS的指令,循环这个指令,直达成功为止

  三个运算符:一个内存地址V,一个期望的值A,一个新值B,

  基本思路:如果地址V上的值和期望的值A相等,就给地址V赋给新值B,如果不是,不做任何操作

  循环(死循坏,自旋)里不断进行CAS操作

  CAS会造成 ABA问题:一个线程t1从内存位置V中取出A,这时候另一个线程t2也从内存中取出A,并且t2进行了一些操作变成了B,然后t2又将V位置的数据变成A,这时候线程t1进行CAS操作发现内存中仍然是A,然后t1操作成功。尽管线程t1的CAS操作成功,但是不代表这个过程就是没有问题的。如果链表的头在变化了两次后恢复了原值,但是不代表链表就没有变化。 一般采用版本号来解决问题。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

码出天空

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

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

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

打赏作者

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

抵扣说明:

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

余额充值