最近在查阅一些源码时,看到里边频繁用到了synchronized这个锁,从而在此重新理解并分析下这个锁的用法
首先先明确一个点:锁的出现一定是为了解决共享资源的操作问题,若不存在共享资源,则没有锁的必要。
在下文中,我们将RESOURCES假定为一个共享资源,我们以下所有的用法都来解决RESOURCES中某个元素的获取,若不存在,则创建该元素并放入共享资源RESOURCES。
我们看具体用法
1、
public synchronized Resource getResource(String namespace) {
Resource resource= RESOURCES.get(namespace);
if (resource == null) {
resource = createResource(namespace);
RESOURCES.put(namespace, resource);
}
return resource;
}
synchronized修饰一个普通对象方法上,此时锁定的是当前对象,即:若多线程下,此对象只有一份(单列),则此处可以满足线程安全
2、
public Resource getResource(String namespace) {
synchronized(this){
Resource resource = RESOURCES.get(namespace);
if (resource == null) {
resource = createResource(namespace);
RESOURCES.put(namespace, resource);
}
return resource;
}
}
synchronized修饰this代码块,此时锁定的也是当前对象,此用法与1不同的是,将锁的粒度降低至方法内部,而不是整个方法,若在此方法内部存在其他逻辑处理,则可提升执行效率,但同样的,必须保证多线程下对象唯一,否则无法保证线程安全。
3、
public synchronized static Resource getResource(String namespace) {
Resource resource = RESOURCES.get(namespace);
if (resource == null) {
resource = createResource(namespace);
RESOURCES.put(namespace, resource);
}
return resource;
}
synchronized修饰类中的静态方法,此时锁定的是整个类,多线程环境下,无需保证此类的对象是否唯一就可满足线程安全的需求。
4、
public Resource getResource(String namespace) {
synchronized(SynchronizedTest.class){
Resource resource = RESOURCES.get(namespace);
if (resource == null) {
resource = createResource(namespace);
RESOURCES.put(namespace, resource);
}
return resource;
}
}
synchronized修饰类的代码块,此时锁定的也是整个类,此用法与3不同的是,将锁的粒度降低至方法内部,而不是整个方法,若在此方法内部存在其他逻辑处理,则可提升执行效率。
以上几种,若正确使用,都可保证线程安全,但都不是最优的使用方式,我们可以看到,不论哪种,为了获取RESOURCES资源中的元素,每次都会经过锁,哪怕是当前元素已存在。
我们来看下以下用法,这也是我在浏览一些源码时,各位前辈所使用的方式
public Resource getResource(String namespace) {
Resource resource = RESOURCES.get(namespace);
if (resource == null) {
synchronized (this) {
resource = RESOURCES.get(namespace);
if (resource == null) {
resource = createResource(namespace);
RESOURCES.put(namespace, resource);
}
}
}
return resource;
}
大家看到,这种用法,在锁之外多加了一次get操作,若此资源已经存在,则不会经过锁,从而提升了效率,只有真正需要修改资源的情况才会进入锁的逻辑。当然,此处是锁定类还是锁定对象,可根据实际情况调整。
以上就是自己对于synchronized关键字的一个小结,此经验充份说明了看源码的好处。我们可以多积累前人的经验与智慧,从而不断提升自己。
本文深入解析synchronized关键字的多种用法及其对线程安全的影响,并介绍了一种通过双检查锁定提高效率的方法。

356

被折叠的 条评论
为什么被折叠?



