java并发问题

并发存在的问题:

  • 可见性:要求一个线程对变量的操作改变对另外一个线程要是可以看见的。例如:当线程1读取主内存中变量到工作内存,线程2也读取并在工作内存改变其值,返回主内存,但线程1还是默认自己工作内存中的值。
  • 原子性:在一次或多次操作中,要么所有的操作都执行不受其他干扰,要么所有的操作都不执行。
  • 有序性:程序中代码的执行顺序,java编译和执行时会对代码进行优化,可能执行顺序与我们编写顺序不一致

java内存模型:

解决原子性问题:synchronized保证只有一个线程拿到锁,能够进入代码块。

解决可见性问题:1.变量加volatile. 2.用synchronized代码段(执行lock指令,使工作内存中共享变量的值更新到主内存,并使其他工作内存中值失效,从而重新去主存中拿实现刷新)

解决有序性问题:1.加了synchronized后这一段代码块的执行顺序无序就没关系了,因为别的代码块必须等这一段都操作完成后才能拿到锁。2.变量加volatile后执行顺序就不重排序

可重入锁:

  • 外层函数获得锁之后 ,内层函数仍然可以获取该锁,synchronized锁的对象中有一个计数器,可以记录线程获得几次该锁,在执行完一次同步代码块计数器减一直到为0释放锁
  • 可重入好处:1.避免死锁 2.更好地让我们封装代码
  • ReentrantLock的tryLock和lock都实现了锁重入,用state+表示

公平锁:

  • 公平锁是指多个线程按照申请锁的顺序来获取锁,类似排队打饭,先来后到

不可中断性:

  • 不可中断定义:一个线程获得锁后,另一个线程想获得该锁必须处于阻塞或等待状态,如果第一个线程不释放锁,那该线程一直保证该状态,该线程状态不可以被中断(thread.interrupt())。
  • 不可中断锁:synchronized,Lock的lock()方法是不可中断锁,tryLock()是可中断锁

synchronized重量级锁种monitor:

  • synchronized的锁对象会关联到一个monitor,是jvm执行到同步代码块,发现锁对象没有monitor,就会创建monitor,monitor有两个重要成员变量,owner:拥有这把锁的线程。recursions:该线程拥有锁的次数。执行到monitorenter时recursions会加1,执行monitorexit时recursions会减一,当recursions减到0这个线程就会释放锁。 monitor才是正真的锁对象
  • 反汇编:线程执行monitorenter,获得该锁 。执行monitorexit,释放该锁
  • 当synchronized出现异常时,会释放锁,执行汇编中monitorexit方法
  • 同步方法(使用synchronized修饰的方法):会隐式调用monitorenter和monitorexit。

CAS(compare and swap):

  • CAS可以保证共享变量赋值时的原子性(两个线程同时修改时,不会出现意外情况)
  • CAS需要有3个操作数:内存地址V,旧的预期值A,即将要更新的目标值B。内存值和预期值一样更新B,不一样则重新去地址拿预期值。
  • CAS机制属于乐观锁,synchronized属于悲观锁

synchronized锁升级过程:

平时代码对synchronized优化

  • 读不加锁,写的时候加锁
  • 减少synchronized的范围
  • 降低synchronized的粒度

synchronized与Lock区别

  • synchronized是一个关键字,Lock是一个接口
  • synchronized会自动释放锁,Lock必须手动释放
  • synchronized是不可中断的,Lock是可中断(tryLock)也可不中断(lock)的
  • Lock可以知道线程有没有拿到锁(Boolean b=lock.tryLock,返回true或者false),而synchronized不能
  • synchronized可以锁住代码块和方法,Lock只能锁代码块
  • Lock(ReentrantReaderLock)可以提高多个线程读的效率
  • synchronized是非公平锁,ReentrantLock可以控制是否是公平锁

as-if-serial:

  • 不管怎么重排序单线程程序的执行结果不能被改变

volatile:

  • 只能修饰变量
  • 不能保证原子性
  • 保证线程可见性:每次读取一个变量都会去主内存中重写读取(执行汇编中lock指令,使工作内存中共享变量的值更新到主内存,并使其他工作内存中值失效,从而重新去主存中拿实现刷新)。
  • 保证执行有序性:加屏障,不可重排序。
  • volatile不会造成线程的阻塞,synchronized会造成线程的阻塞

ReentrantLock :

  •  tryLock:表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false,也就说这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待

  • ReentrantLock的tryLock和lock都实现了锁重入,用state+1表示表示锁状态
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值