美文网首页
线程:并发问题

线程:并发问题

作者: 寂静的春天1988 | 来源:发表于2019-01-16 10:55 被阅读0次

    多个线程访问同一份资源,就会产生线程安全问题。
    1)可以使用synchronized修饰方法,那么它会阻塞线程,一个线程访问,那么其他线程必须等待!
    2)可以使用同步代码块
    synchronized (this){

    }
    同步代码块的形参必须是引用类型,同步代码块容易犯的错:
    2.1锁定范围不正确,范围过大,效率低下。范围过小,没有起到线程安全的效果。
    2.2锁定资源不正确。

    单例模式(恶汉式)

    public static void main(String[] args) {
            DemoThread d1=new DemoThread();
            DemoThread d2=new DemoThread();
            d1.start();
            d2.start();
        }
    }
    
    class Demo{
        private static Demo demo=null;
        private Demo(){
            
        }
        public static Demo getDemo(){
            if(demo==null){
                try {
                    Thread.sleep(10000);//模拟网络延时等
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                demo=new Demo();
            }
            return demo;
        }
    }
    class DemoThread extends Thread{
        @Override
        public void run() {
            Demo demo = Demo.getDemo();
            System.out.println(demo);
        }
        
    }
    

    可以发现由于网络延时等原因,发现上面那段代码在多线程下也有可能创建两个对象
    1、可以使用同步方法解决,直接加上synchronized修饰getDemo方法
    2、使用同步代码块

    public static  Demo getDemo(){
            synchronized(Demo.class){
                if(demo==null){
                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    demo=new Demo();
                }
            }
            
            return demo;
        }
    

    上面可以解决,但是发现效率不高,如果对象不为null,那么也要进入同步代码块。可以优化成以下代码

    public static  Demo getDemo(){
            if(demo==null){
                synchronized(Demo.class){
                    if(demo==null){
                        try {
                            Thread.sleep(10000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        demo=new Demo();
                    }
                }
            }
            return demo;
        }
    

    仔细分析代码可以发现,只需要对象为null时进入同步代码块,所以加了一个if(demo==null)的判断

    相关文章

      网友评论

          本文标题:线程:并发问题

          本文链接:https://www.haomeiwen.com/subject/qfipdqtx.html