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

来源:互联网 发布:windows手写笔记软件 编辑:程序博客网 时间:2024/05/02 05:03

来源: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