这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战
同步的基本思想
目的:为了保证共享数据在同一时刻只被一个线程使用,我们有一种很简单的实现思想,就是
1.在共享数据里保存一个锁 ,当没有线程访问时,锁是空的。
2.当有第一个线程访问时,就 在锁里保存这个线程的标识 并允许这个线程访问共享数据。
3.在当前线程释放共享数据之前,如果再有其他线程想要访问共享数据,就要 等待锁释放 。
Synchronized 和 Lock的 区别
1、Synchronized 内置的Java关键字,Lock是一个接口有着众多的实现类
2、Synchronized 无法判断获取锁的状态,Lock 可以判断是否获取到了锁
Lock类中存在方法
boolean tryLock(); // 尝试获取锁,如果获取成功则证明该锁之前未被占用,如果返回false则证明该锁已被占用
3、Synchronized 会自动释放锁所以被称为隠式锁,lock必须要手动释放锁所以被称为显式锁,如果不释放锁,就会导致死锁
package com.cheng.PC;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@SuppressWarnings({"all"})
class Data03{
private int num = 10;
private Lock lock = new ReentrantLock();
/**
* 使用Lock(显式锁)
*/
public void add(){
try {
lock.lock(); // 上锁
if (num < 10){
num ++;
}
} catch (Exception e) {
e.printStackTrace();
} finally {// 操作结束以后必须执行解锁
lock.unlock(); // 解锁
}
}
/**
* 使用synchronized(隠式锁)
*/
public synchronized void recede(){
if (num > 0){
num --;
}
}
}
4、使用Synchronized时如果一个线程已经获得了锁,那么其他线程则一定会处于阻塞状态,直到该线程释放锁为止。而使用Lock锁时,因为Lock接口提供了boolean tryLock()方法可以使其它的线程尝试取得锁所以不一定都会处于阻塞状态。
5、因为Synchronized是Java内置关键字所以已经写定了是可重入锁,不可以中断的,非公平锁;而Lock接口存在多个实现类所以可以自己设置相关锁的特性
6、Synchronized 适合少量代码同步问题,Lock 适合锁大量的同步代码
总结:
形象的来说
synchronized(隠式锁)像汽车中的自动档,许多东西都已经帮你设定好了,使用起来方便但是不太灵活
Lock(显式锁)则像手动挡,需要你操作的东西更多但是更加灵活多变,并且在Lock实现类中,也扩展了许多方法可以在你使用的时候更加顺手。