目录
Synchronized同步锁
synchronized的用法:
ReentrantLock
ReentrantLock和Synchronized的区别
文章来源:https://www.toymoban.com/news/detail-596738.html
Synchronized同步锁
使用Synchronized关键字将一段代码锁起来,同一时间只允许一个线程访问。只有获取了这把锁的线程才能访问这段代码,并且只有一个线程拥有这把锁。这样就保证了代码的安全性。
synchronized的用法:
1.修饰实例方法:synchronized修饰实例方法,则用到的锁,默认为this当前方法调用对象。
只有获取this锁的线程才能访问当前方法。同一时刻只有一个线程持有this锁。
public synchronized void add() {
}
public void add1() {
synchronized(this) {
}
}
//使用synchronized关键字修饰方法时,两种写法作用与意义相同
2.修饰静态方法 :修饰静态方法,用到的锁,默认为当前类的Class对象
public synchronized static void add() {
}
3.修饰代码块:修饰代码块,用到的锁是可以指定的,为指定的某类对象。
Object obj = new Object();
public void de() {
synchronized(obj) {
}
}
当一个线程访问对象的一个synchronized(this)同步代码块时,另一线程仍然可以访问该对象中的非synchronized(this)同步代码块。
父类中synchronized修饰的方法,如果子类没有重写,,则该方法仍然是线程安全的;如果子类重写,并没有使用synchronized修饰,则该方法是线程不安全的。
定义接口方法时,不能使用synchronized关键字;
构造方法不能使用synchronized关键字,但是可以使用synchronized代码块来进行同步。
离开synchronized代码块后,该线程持有的锁,自动释放。
ReentrantLock
ReentrantLock是Java中一种可重入锁。
重入锁:一个线程,在获取锁后,可以继续获取同一个锁
public class Counter {
private int count = 0;
public synchronized void add(int n) {
if (n < 0) {
dec(-n);
} else {
count += n;
}
}
public synchronized void dec(int n) {
count += n;
}
}
//当执行add()方法后,会继续调用dec()方法,dec方法也需要获取this锁。
JVM允许同一个线程重复获取同一个锁,这种能被反复获取的锁,叫可重入锁。
ReentrantLock是可重入锁,synchronized也是可重入锁。
在获取可重入锁时,要记录这是第几次获取,没获取一次记录+1,每次退出可重入锁,记录-1,减到0时,才会真正释放锁。
public class Counter {
private final Lock lock = new ReentrantLock();
private int count;
public void add(int n) {
lock.lock();
try {
count += n;
} finally {
lock.unlock();
}
}
}
ReentrantLock是JavaSE 核心类库的并发包(java.util.concurrent)提供的可重入锁,所以以防有异常发生,无法正常释放锁所以在创建锁后,在finally中释放锁。
ReentrantLock还可以尝试获取锁:
if (lock.tryLock(1, TimeUnit.SECONDS)) {
try {
...
} finally {
lock.unlock();
}
}
尝试获取锁,最多等待一秒。一秒后,还未获取到锁,直接返回false,程序可以尝试做一些额外的处理,而不是无线等待。
所以,ReentrantLock比synchronized更安全,在使用tryLock()失败后不会产生死锁。
ReentrantLock内部有三个类:Sync、NonfairSync、FairSync。
NonfairSync类继承了Sync类,表示采用非公平策略获取锁:每一次都尝试获取锁,不会按照公平等待的原则进行等待,不会让等待最久的线程获得锁。
FairSync类也继承了 Sync类,表示采用公平策略获取锁:当资源空闲时,它总是会先判断 sync队列是否有等待时间更长的线程,如果存在,则将当前线程加入到等待队列的尾部,实现了公平获取原则。
ReentrantLock构造函数:默认是采用的非公平策略获取锁。
ReentrantLock(boolean) 构造函数:可以传递参数确定采用公平策略或者是非公平策略,参数为 true表示公平策略,否则,采用非公平策略。
ReentrantLock和Synchronized的区别
ReentrantLock | Synchronized | |
---|---|---|
锁实现机制 | AQS | 监视器Monitor |
获取锁 | 可以通过tryLock()尝试获取锁,更灵活 | 线程抢占模型 |
释放锁 | 必须显示通过unlock()释放锁 | 自动释放 |
锁类型 | 支持公平锁和非公平锁 | 非公平锁 |
可重入性 | 可重入 | 可重入 |
文章来源地址https://www.toymoban.com/news/detail-596738.html
到了这里,关于《ReentrantLock与synchronized的区别》的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!