• synchronized双重校验问题


      今天写synchronized用例的时候,两个线程共享一个对象数据,当操作i的时候,在同步代码块外面判断了一次i<100,但是每一次跑,都会出现i=100,的情况。此时我想起了单例模式的双重校验锁,为什么要判断两次呢?因为可能出现线程1和线程2,在i=99的时候,同时判断了一次,都进到了for循环里面,此时线程1进入同步代码块,线程2进如阻塞队列。当线程1时间片用完,但是代码块并没有执行完。此时,线程2也满足if条件进入同步代码块,之后就会出现线程1和线程2都对i进行了加1,就输出i = 100(同理·,如果三个线程则可能出现101的情况),所以要在同步代码块中再加一次判断,判断i的值

      synchronized代码块使用起来比synchronized方法要灵活得多。因为也许一个方法中只有一部分代码只需要同步,如果此时对整个方法用synchronized进行同步,会影响程序执行效率。而使用synchronized代码块就可以避免这个问题,synchronized代码块可以实现只对需要同步的地方进行同步

    import java.util.ArrayList;
    
    /**
     * @Classname DoubleChecking
     * @Description TODO
     * @Date 2020/7/21 13:20
     * @Created by Fearless
     */
    public class DoubleChecking {
        public class Data{
            private ArrayList<Integer> arr = new ArrayList<>();
            private Integer i ;
            public void insert(){
                for (i = 0 ; i < 100 ; ++i){
                    synchronized (this){
                        //再次校验避免阻塞线程改变i值
                        if (i < 100){
                            if (!arr.contains(i)){
                                arr.add(i);
                                System.out.println(Thread.currentThread().getName()+"正在插入"+i);
                            }
                        }
                    }
                }
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
            DoubleChecking doubleChecking = new DoubleChecking();
            Data data = doubleChecking.new Data();
            new Thread(() -> data.insert(),"t1").start();
            new Thread(() -> data.insert(),"t2").start();
            Thread.sleep(3000);
        }
    }
  • 相关阅读:
    IDEA调试快捷键
    视频预览
    文件上传:简单的demo
    Java 运行时优化
    Java 类加载
    Java StringTable
    Java 为什么不用Vector
    C++ 查找函数
    JVM 垃圾回收
    JVM 直接内存
  • 原文地址:https://www.cnblogs.com/skyblue123/p/13354779.html
Copyright © 2020-2023  润新知