2021-06-05# Java基础(dayFourteen):锁的两种方式,字节跳动服务端研发面试

  • 公平锁

  • 条件对象

  • synchronized关键字

    • 静态同步方法
  • 同步块

并发同步


当两个或两个以上的线程需要共享对同一数据的存取或修改时,会发生覆盖现象,覆盖情况取决于线程调度器先调度哪一个线程,这种情况通常称为竞态条件

锁对象

Java提供两种机制防止并发访问代码块

【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】

浏览器打开:qq.cn.hn/FTf 免费领取
  1. Synchronized关键字

  2. ReentrantLock类

ReentrantLock

使用ReentrantLock来进行加锁的话,都是要用在try语句上(即lock方法后面必须紧跟try语句),最后一定要用finally来释放锁

在这里插入图片描述

该结构确保了在任何时刻只有一个线程可以进入下面的lock后的语句块里面,也就是临界区

一旦一个线程锁定了锁对象,其他任何线程都无法通过lock语句,当其他线程调用lock时,则会进行暂停,直到前面的线程释放这个锁对象,也就是unlock

举个栗子

下面是某类加锁的方法

在这里插入图片描述

测试的main方法

在这里插入图片描述

结果为

在这里插入图片描述

可以看到在lock前面的代码是可以让其他线程执行的,但是lock后面的代码必须等待前面的线程释放锁才可以去执行,期间就会发生阻塞

这里要注意的是,每个对象会有自己的ReentrantLock,所以要争抢同一个ReentrantLock对象才会发生阻塞,该锁就可以保证串行化访问,如果是两个不同的对象,以上个栗子为例,就是两个不同的TestSyncFunny对象,那么两个线程得到的是不同的锁,是不会发生阻塞现象的

这个锁称为重入锁(ReentrantLock:重入),因为这个锁可以被线程反复获得,该锁会有一个持有计数来跟踪对lock方法的嵌套使用,即在加锁的try语句块里面调用方法A,该方法A加的是同一把锁(同一个ReentranLock),所以获得B的锁也会去影响A的运行

举个栗子

private ReentrantLock lock = new ReentrantLock();

public void doSyncTo(String name){

System.out.println(“下面”+name+“也要进行加锁”);

lock.lock();

try{

System.out.println(name+“已经加锁了~~~~”);

Thread.sleep(2000);

} catch (InterruptedException e) {

e.printStackTrace();

} finally {

lock.unlock();

}

}

public void doSync(String name){

System.out.println(name+“还没进行上锁----”);

lock.lock();

try{

System.out.println(name + “上锁了,dododoodid”);

doSyncTo(name);

System.out.println(name+“调用完了另一个加锁方法,并且已经释放那个锁了”);

Thread.sleep(2000);

System.out.println(name+“睡醒了”);

//code…

} catch (InterruptedException e) {

e.printStackTrace();

} finally {

lock.unlock();

}

}

上面是两个加锁的方法,用都是同一个ReentrantLock,而且在doSync方法中,还调用了doSyncTo的方法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值