A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 代瑞朋 中级黑马   /  2013-12-8 11:31  /  1585 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 代瑞朋 于 2013-12-9 08:59 编辑

class Single
{
        private static Single s=null;
        private Single(){}
        public static Single getInstance()
        {
                if (s==null)
                {
                        synchronized(Single.class)
                        {
                                if (s==null)
                                        s=new Single();
                        }
                }
                return s;
        }
}

评分

参与人数 1技术分 +1 收起 理由
简★零度 + 1

查看全部评分

7 个回复

倒序浏览
同步代码,防止多线程在懒汉式模式时创建多个对象,保证对象唯一性
回复 使用道具 举报
因为单例只能创建一个对象,如果出现在并发代码中,调用getInstance()时不同步的话可能造成同时创建俩单例,很明显,这是不对的,所以为了防止这种情况发生,必须同步,消除同时创建几个单例对象的可能性。
回复 使用道具 举报
synchronized 是做线程同步的,在同步代码块中,锁可以是任意的一个对象.例如
synchronized(new Object());
在同步函数中,默认的锁是this,谁调用了这个函数,就使用哪个对象作为锁.要两个以上的线程都使用这个锁才可以达到同步的效果,否则还是不安全的.
在静态代码函数中,synchronized用的锁对象是当前类的字节码文件对象.例如在Person中写的静态同步函数,它的锁就是Person.class这个Class类的对象.同意楼上所说的

评分

参与人数 1技术分 +1 收起 理由
简★零度 + 1

查看全部评分

回复 使用道具 举报
这是单例设计模式中懒汉式的实现方式。
synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程(例如线程A),运行到这个方法时,都要检查有没有其它线程B(或者C、 D等)正在用这个方法,有的话要等正在使用synchronized方法的线程B(或者C 、D)运行完这个方法后再运行此线程A,没有的话,直接运行。
也就是说,如果多个线程同时访问一个共享数据时,有可能会发生错误,这个在老毕的视频中演示的很明白。
synchronized就是把访问共享数据的代码封装起来,当多个线程执行到这些代码时会判断锁,取得锁后就执行代码,而且吧代码块执行完成后才能释放锁,其他的线程在这个期间只能等待。保证同一时刻只能有一个线程执行这些操作共享数据的代码,保证共享数据的安全。

评分

参与人数 1技术分 +1 收起 理由
简★零度 + 1

查看全部评分

回复 使用道具 举报
首先这个是按照单例设计模式写的代码,单例设计模式分为两种,一种饿汉式,一种懒汉式
你这个是懒汉式
而懒汉式的特点在于,对象的延迟加载
这样在多线程中就出现了安全问题
要用加同步也就是synchronized的方式来解决
而加了同步就会使代码的效率降低
因为每一个线程都要判断锁
那就要用双重判断来解决

评分

参与人数 1技术分 +1 收起 理由
简★零度 + 1

查看全部评分

回复 使用道具 举报
这个小程序是一个延迟加载的单例设计模式:懒汉式。
懒汉式:用于实例的延迟加载。
延迟加载主要体现在多个线程访问情况下,每个线程都要访问这个实例,都要判断下同步中的锁,会很低效。

懒汉式的延迟加载有什么问题,是什么问题?
如果多线程进行访问时,会出现安全问题。

出现这些问题要去怎么解决?
可以加同步解决,关键字:synchronized。用同步函数或者同步代码块解决。
但稍微有些低效,用双重判断的的方式能解决效率这个问题,上面的小程序中,被if体现。

加同步使用的锁是哪一个?
该类所属的字节码文件对象,被Single.class体现。

补充:
如果同步函数被静态修饰后,使用的锁是什么呢?
静态方法中也不可以定义this,所以不是this,因为,静态进内存,内存中没有本类对象。
但是一定有该类对应的字节码文件对象,类名.class。
简单说:静态同步函数的锁是Class对象

关于synchronized的小结:
synchronized,可以锁方法,也可以锁代码块,对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以参与执行。
Java对于多线程的安全问题提供了专业的解决方式,就是同步代码块。哪些代码需要同步就看哪些代码操作共享数据

Synchronized(对象){
需要同步的代码
}

对象如同锁,持有锁的线程可以再同步中执行,没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。同步可以解决线程的安全问题,同步的前提:
1、 必须要有两个或者两个以上的线程才需要同步。
2、 必须是多个线程使用同一个锁。
3、 必须保证同步中只能有一个线程在运行。

同步的好处和弊端:
好处:解决了多线程的安全问题
弊端:多个线程都需要判断锁,较为消耗资源。

评分

参与人数 1技术分 +1 收起 理由
简★零度 + 1

查看全部评分

回复 使用道具 举报
史超 中级黑马 2013-12-8 16:36:20
8#
synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块。
1. synchronized 方法:通过在方法声明中加入 synchronized关键字来声明 synchronized 方法。如:
public synchronized void accessVal(int newVal);
synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。
在 Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成员变量的访问。
synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法 run() 声明为 synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。当然我们可以通过将访问类成员变量的代码放到专门的方法中,将其声明为 synchronized ,并在主方法中调用来解决这一问题,但是 Java 为我们提供了更好的解决办法,那就是 synchronized 块。
2. synchronized 块:通过 synchronized关键字来声明synchronized 块。语法如下:
synchronized(syncObject) {
//允许访问控制的代码
}
??synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行,具体机制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。

评分

参与人数 1技术分 +1 收起 理由
简★零度 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马