聊之前先说一下并发编程的3个特性。
volatile是JVM提供的最轻量级的同步机制,编译器不会对其进行优化。
(相关资料图)
volatile只能用来修饰成员变量。
public class VolatileTest {
private volatile static String staticVolatile;
private volatile String memberVolatile;
}
synchronized关键字是java提供的内置锁来保证我们对共享资源的同步,它会自动加锁和释放锁,它的锁是非公平锁, synchronized关键字标记的地方会被编译器进行优化。synchronized会使线程串行执行,可能会造成线程阻塞。
synchronized关键字可用来修饰方法或者代码块。
public synchronized void objectMethods(){
.....
}
修饰静态方法,类锁
public static synchronized void staticMethods(){
.....
}
obj为对象的引用 对象锁
public void objectMethods(){
synchronized (obj){
}
}
Object 为某个类 类锁
public void classLock(){
synchronized (Object.class){
}
}
Lock是 Java 5提供的一个具有锁机制的接口,ReentrantLock是Lock的一个实现,内部是通过AQS(AbstractQueuedSynchronizer)实现的。ReentrantLock翻译过来是可重入锁,它和synchronized类似,ReentrantLock需要手动加锁和释放锁, 相对于synchronized它更加灵活,提供了更多的方法。 ReentrantLock有公平锁和非公平锁两种方式,默认是使用公平锁。
ReentrantLock是可重入的同步锁,所以它除了具有并发编程的三大特性,还具有可重入性。
ReentrantLock是一个类,它既可以作为成员变量,也可以作为局部变量使用。做为成员变量和局部变量时,使用的方式有一点点不同,不管使用哪种方式,最后都别忘了要调用unlock()方法手动释放锁。
private Lock globalLock = new ReentrantLock();
public void globalLock(){
if (globalLock.tryLock()) {
try {
} catch (Exception e) {
}finally {
globalLock.unlock();
}
}
}
上面的tryLock()方法是尝试获取锁,如果获取成功返回true,否则返回false,也可以换成加了等待时间的 boolean tryLock(long time, TimeUnit unit)方法,在设定的等待时间内获取锁成功则返回true,否则false。
public void lock(){
Lock lock = new ReentrantLock();
lock.lock();
try {
}finally {
lock.unlock();
}
}
简单对比一下三者之间的区别:
| volatile | synchronized | ReentrantLock | |
| 是否是关键字 | 是 | 是 | 否 |
| 是否需要手动加锁/释放锁 | 否 | 否 | 是 |
| 是否能保证并发安全 | 否 | 是 | 是 |
| 是否是公平锁 | \ | 否 | 有公平锁和非公平锁两种实现 |
| 是否会阻塞线程 | 否 | 是 | 是 |
| JVM是否会对其优化 | 否 | 是 | 否 |
| 特性 | 可见性、有序性 | 可见性、有序性、原子性 | 可见性、有序性、原子性 |
| 使用的地方 | 成员变量 | 方法、代码块 | 成员变量、局部变量 |
到此这篇关于关于synchronized、volatile、ReentrantLock的区别与对比的文章就介绍到这了,更多相关synchronized、volatile、ReentrantLock的区别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
Copyright 2015-2022 东方服务网 版权所有沪ICP备2020036824号-8
邮箱:562 66 29@qq.com