问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

java锁的可见性的是怎么保证的

发布网友 发布时间:2022-04-23 01:40

我来回答

2个回答

热心网友 时间:2022-04-23 07:27

单例类在Java开发者中非常常用,但是它给初级开发者们造成了很多挑战。他们所面对的其中一个关键挑战是,怎样确保单例类的行为是单例?也就是说,无论任何原因,如何防止单例类有多个实例。在整个应用生命周期中,要保证只有一个单例类的实例被创建,双重检查锁(Double checked locking of Singleton)是一种实现方法。顾名思义,在双重检查锁中,代码会检查两次单例类是否有已存在的实例,一次加锁一次不加锁,一次确保不会有多个实例被创建。顺便提一下,在JDK1.5中,Java修复了其内存模型的问题。在JDK1.5之前,这种方法会有问题。本文中,我们将会看到怎样用Java实现双重检查锁的单例类,为什么Java 5之前的版本双重检查锁会有问题,以及怎么解决这个问题。顺便说一下,这也是重要的面试要点,我曾经在金融业和服务业的公司面试被要求手写双重检查锁实现单例模式、相信我,这很棘手,除非你清楚理解了你在做什么。你也可以阅读我的完整列表“单例模式设计问题”来更好的准备面试。
为什么你需要双重检查锁来实现单例类?
一个常见情景,单例类在多线程环境中违反契约。如果你要一个新手写出单例模式,可能会得到下面的代码:
private static Singleton _instance;

public static Singleton getInstance() {
if (_instance == null) {
_instance = new Singleton();
}
return _instance;
}

然后,当你指出这段代码在超过一个线程并行被调用的时候会创建多个实例的问题时,他很可能会把整个getInstance()方法设为同步(synchronized),就像我们展示的第二段示例代码getInstanceTS()方法一样。尽管这样做到了线程安全,并且解决了多实例问题,但并不高效。在任何调用这个方法的时候,你都需要承受同步带来的性能开销,然而同步只在第一次调用的时候才被需要,也就是单例类实例创建的时候。这将促使我们使用双重检查锁模式(double checked locking pattern),一种只在临界区代码加锁的方法。程序员称其为双重检查锁,因为会有两次检查 _instance == null,一次不加锁,另一次在同步块上加锁。这就是使用Java双重检查锁的示例:
public static Singleton getInstanceDC() {
if (_instance == null) { // Single Checked
synchronized (Singleton.class) {
if (_instance == null) { // Double checked
_instance = new Singleton();
}
}
}
return _instance;
}

这个方法表面上看起来很完美,你只需要付出一次同步块的开销,但它依然有问题。除非你声明_instance变量时使用了volatile关键字。没有volatile修饰符,可能出现Java中的另一个线程看到个初始化了一半的_instance的情况,但使用了volatile变量后,就能保证先行发生关系(happens-before relationship)。对于volatile变量_instance,所有的写(write)都将先行发生于读(read),在Java 5之前不是这样,所以在这之前使用双重检查锁有问题。现在,有了先行发生的保障(happens-before guarantee),你可以安全地假设其会工作良好。另外,这不是创建线程安全的单例模式的最好方法,你可以使用枚举实现单例模式,这种方法在实例创建时提供了内置的线程安全。另一种方法是使用静态持有者模式(static holder pattern)。
/*
* A journey to write double checked locking of Singleton class in Java.
*/

class Singleton {

private volatile static Singleton _instance;

private Singleton() {
// preventing Singleton object instantiation from outside
}

/*
* 1st version: creates multiple instance if two thread access
* this method simultaneously
*/

public static Singleton getInstance() {
if (_instance == null) {
_instance = new Singleton();
}
return _instance;
}

/*
* 2nd version : this definitely thread-safe and only
* creates one instance of Singleton on concurrent environment
* but unnecessarily expensive e to cost of synchronization
* at every call.
*/

public static synchronized Singleton getInstanceTS() {
if (_instance == null) {
_instance = new Singleton();
}
return _instance;
}

/*
* 3rd version : An implementation of double checked locking of Singleton.
* Intention is to minimize cost of synchronization and improve performance,
* by only locking critical section of code, the code which creates instance of Singleton class.
* By the way this is still broken, if we don't make _instance volatile, as another thread can
* see a half initialized instance of Singleton.
*/

public static Singleton getInstanceDC() {
if (_instance == null) {
synchronized (Singleton.class) {
if (_instance == null) {
_instance = new Singleton();
}
}
}
return _instance;
}
}

这就是本文的所有内容了。这是个用Java创建线程安全单例模式的有争议的方法,使用枚举实现单例类更简单有效。我并不建议你像这样实现单例模式,因为用Java有许多更好的方式。但是,这个问题有历史意义,也教授了并发是如何引入一些微妙错误的。正如之前所说,这是面试中非常重要的一点。在去参加任何Java面试之前,要练习手写双重检查锁实现单例类。这将增强你发现Java程序员们所犯编码错误的洞察力。另外,在现在的测试驱动开发中,单例模式由于难以被模拟其行为而被视为反模式(anti pattern),所以如果你是测试驱动开发的开发者,最好避免使用单例模式。

热心网友 时间:2022-04-23 08:45

网页链接

应该和happens-before有关

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
电脑音乐怎样保存到文件中怎样把歌曲放到文件夹里 电脑上如何把歌曲做成文件夹怎么把歌曲转化为文件 如何把音频加入到电脑文件夹上怎么把歌曲放到文件夹中 海参是不是吃多长时间以后可以不用在吃了 梦见一半黑色 电吉他买了音箱还要买效果器吗 有人去过资和信百货吗? 资和信百货企业理念 资和信百货家庭季家庭季简介 资和信是什么 JAVA锁机制 有小例子说明最好! JAVA多线程中“锁”的概念的理解 Java多线程中,锁是什么,所谓的获取锁是什么意思 java中文件加锁机制是怎么实现的。 java为什么要对对象加锁 java中共享锁与无锁的区别? Java的锁机制有什么用 java 多线程什么是锁 经常会听到Java锁这个词,但给自己的感觉很朦胧,有办法清楚的了解它吗?大虾们给个建议!!! Java锁的几种应用 说说java锁有哪些种类,以及区别 java 对象锁和方法锁有什么区别 如何使用java的锁机制 java中的锁有哪几种 java中的lock锁,多次获得,只unlock一次,会有什么效果 Java中有哪些锁,区别是什么 JAVA锁有哪些种类,以及区别 唯品会月度账单可以删除吗? 小龙虾和普通的虾有何区别?一共有哪些虾?常见的可养殖虾品种有哪些? 龙虾是海虾吗? java中如何锁住一个文件不让其他程序修改 wps怎么把文本转换成表格 怎样把wps文字转换成wps表格? 怎么把手机wpsword转换为Excel文档? 香椿用开水烫过后可以保存多久?怎么保存? 香椿的如何保存一年四季都可以吃到? 香椿如何保存? 香椿可以冷冻保存吗? 怎么保存新鲜的香椿? 忘记了股票交易密码和资金账号怎么办 股票交易密码和通讯密码忘了怎么办 股票的交易密码和通讯密码忘记该如何处理 怎样破解股票交易密码 股票交易密码忘记了 微信如果把好友拉黑单后,再从黑名单里删除! .这时会出现什么情况?详细的………_百度问一问 当微信好友把我加入黑名单,并且删除好友后,我领了他的转账他的微信会显示出来? 微信好友加入黑名单后删除了,为什么黑名单里还显示这个人? 微信加入黑名单和删除好友有什么区别? 如果对方微信没有删除我,仅仅是拉进了黑名单,我这里会有什么显示 微信黑名单和删除好友什么区别?