线程同步与锁定_synchronized_单例模式_doubleCheckingJAVA178-179

来源:http://www.bjsxt.com/
一、S02E178_01线程同步与锁定1_synchronized
——由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题。Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问。
——由于我们可以通过private关键字来保证数据对象只能被方法访问,所以我们只需针对方法提出一套机制,这套机制就是synchronized关键字,它包括两种用法:synchronized方法和synchronized块
——同步:并发,多个线程访问同一份资源(确保资源安全–>>线程安全)
1、同步块
——synchronized(引用类型或者this或者类.class){
}
2、同步方法
——synchronized

package com.test.thread.syn;

public class SynDemo {
    public static void main(String[] args) {
        //真实角色
        Web12306 web = new Web12306();
        //代理
        Thread t1 = new Thread(web, "路人甲");
        Thread t2 = new Thread(web, "黄牛乙");
        Thread t3 = new Thread(web, "攻城狮");
        t1.start();
        t2.start();
        t3.start();
    }
}
class Web12306 implements Runnable {
    private int num = 10;//1到10号
    private boolean flag = true;
    @Override
    public void run(){
        while(flag) {
            //test1();
            //test2();
            //test3();
            //test4();
            //test5();
            test6();
        }
    }
    //线程不安全
    public void test1(){
        if(num <= 0){
            flag = false;//跳出循环
            return;
        }
        try {
            Thread.sleep(500);//模拟延时
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "抢到了" + num--);
    }
    //同步方法,线程安全,锁定正确
    public synchronized void test2(){
        if(num <= 0){
            flag = false;//跳出循环
            return;
        }
        try {
            Thread.sleep(500);//模拟延时
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "抢到了" + num--);
    }
    //同步块,线程安全,锁定正确
    public void test3(){
        synchronized(this){
            if(num <= 0){
                flag = false;//跳出循环
                return;
            }
            try {
                Thread.sleep(500);//模拟延时
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "抢到了" + num--);
        }
    }
    //锁定范围不正确
    public void test4(){
        synchronized(this){
            if(num <= 0){
                flag = false;//跳出循环
                return;
            }
        }
        try {
            Thread.sleep(500);//模拟延时
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "抢到了" + num--);
    }
    //线程不安全,锁定资源不正确
    public void test5(){
        synchronized((Integer)num){
            if(num <= 0){
                flag = false;//跳出循环
                return;
            }
            try {
                Thread.sleep(500);//模拟延时
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "抢到了" + num--);
        }
    }
    //锁定范围不正确
    public void test6(){
        if(num <= 0){
            flag = false;//跳出循环
            return;
        }
        synchronized(this){
            try {
                Thread.sleep(500);//模拟延时
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "抢到了" + num--);
        }
    }
}

二、S02E179_01线程同步与锁定2_synchronized_单例模式_doubleChecking

package com.test.thread.syn;
/**
 * 单例设计模式:外部使用时确保一个类只有一个对象(内部创建,外部不能创建,只能使用)
 */
public class Singleton {
    public static void main(String[] args) {
        JvmThread thread1 = new JvmThread(100);
        JvmThread thread2 = new JvmThread(100);
        thread1.start();
        thread2.start();
    }
}
class JvmThread extends Thread{
    private long time;

    public JvmThread(){
    }
    public JvmThread(long time){
        this.time = time;
    }
    @Override
    public void run(){
        System.out.println(Thread.currentThread().getName()+"-->"+Jvm.getInstance(time));
    }
}
/**
 * 单例设计模式
 * 外部使用时确保一个类只有一个对象(内部创建,外部不能创建,只能使用)
 * 懒汉式  double checking
 * 1、构造器私有化,避免外部直接创建对象
 * 2、声明一个私有的静态变量
 * 3、创建一个对外的公共的静态方法访问该变量,如果变量没有对象,创建该对象
 */
class Jvm{
    //声明一个私有的静态变量
    private static Jvm instance = null;//懒得创建对象

    //构造器私有化,避免外部直接创建对象
    private Jvm(){
    }

    //创建一个对外的公共的静态方法访问该变量,如果变量没有对象,创建该对象
    //一、不同步,产生多个对象
    public static Jvm getInstance1(long time){
        if(null==instance){
            try {
                Thread.sleep(time);//延时,放大发生错误的概率
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            instance = new Jvm();
        }
        return instance;
    }
    //二、加入synchronized,成为同步方法,只有一个对象
    public static synchronized Jvm getInstance2(long time){
        if(null==instance){
            try {
                Thread.sleep(time);//延时,放大发生错误的概率
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            instance = new Jvm();
        }
        return instance;
    }
    //三、同步块,只有一个对象,效率不高,存在对象也需要等待
    public static Jvm getInstance3(long time){
        //a、b、c、d线程进来都需要等待,效率不高,存在对象也需要等待
        synchronized(Jvm.class){//锁住类的字节码信息
            if(null==instance){
                try {
                    Thread.sleep(time);//延时,放大发生错误的概率
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                instance = new Jvm();
            }
            return instance;
        }
    }
    //四、同步块,只有一个对象,doubleChecking提高已经存在对象的访问效率
    public static Jvm getInstance(long time){
        //第二段:后来c、d线程都进来判断,发现有对象,直接返回,不用等待
        if(null==instance){
            //第一段:刚开始a、b线程都进来等待,a进入创建对象后,b再进入后发现有对象就直接返回
            synchronized(Jvm.class){//锁住类的字节码信息
                if(null==instance){
                    try {
                        Thread.sleep(time);//延时,放大发生错误的概率
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    instance = new Jvm();
                }
            }
        }
        return instance;
    }
}
package com.test.thread.syn;
/**
 * 单例创建的方式
 * 1、懒汉式
 *  1)构造器私有化
 *  2)声明私有的静态属性
 *  3)对外提供访问属性的静态方法,确保该对象存在
 */
public class MyJvm {
    private static MyJvm instance;
    private MyJvm(){
    }

    public static MyJvm getInstance(){
        if(null==instance){//提高效率
            synchronized(MyJvm.class){
                if(null==instance){//安全
                    instance = new MyJvm();
                }
            }
        }
        return instance;
    }
}
/**
 * 饿汉式
 *  1)构造器私有化
 *  2)声明私有的静态属性,同时创建该对象
 *  3)对外提供访问属性的静态方法,确保该对象存在
 */
class MyJvm2 {
    private static MyJvm2 instance = new MyJvm2();
    private MyJvm2(){
    }

    public static MyJvm2 getInstance(){
        return instance;
    }
}
/**
 * 类在使用时加载,延缓加载时机,提高效率
 */
class MyJvm3 {
    private static class JvmHolder{//内部类,使用时加载
        private static MyJvm3 instance = new MyJvm3();
    }

    private MyJvm3(){
    }

    public static MyJvm3 getInstance(){
        return JvmHolder.instance;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值