-
公平锁
-
条件对象
-
synchronized关键字
-
- 静态同步方法
-
同步块
当两个或两个以上的线程需要共享对同一数据的存取或修改时,会发生覆盖现象,覆盖情况取决于线程调度器先调度哪一个线程,这种情况通常称为竞态条件
锁对象
Java提供两种机制防止并发访问代码块
【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
-
Synchronized关键字
-
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的方法