线程安全相关概念

  • 线程安全:当多个线程访问某个类时,不管运行时环境采用和种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的。
  • 竞态条件:基于一种可能失效的观察结果来做出判断或者执行某个计算。这种类型的竞态条件称为“先检查后执行”,常见的例子就是i++,以及if(condition) then dosometing。
  • 数据竞争:容易跟竞态条件混淆,指如果在访问共享的非final类型的域时没有采用同步来协同,那么就会出现数据竞争,常见于java内存模型。
  • 内置锁,监视器锁:本质是互斥锁,Monitor enter,Monitor exit
  • 内存可见性:防止某个线程正在使用对线状态而另外一个线程在同时修改该状态,确保当一个线程修改了对象状态后,其他线程能够看到发生的状态变化。
  • 重排序:以下这段代码可能存在重排序问题导致输出为0。  0.0
  •  1 public class NoVisibility {
     2     private static boolean ready;
     3     private static int number;
     4 
     5     private static class ReaderThread extends Thread {
     6         public void run() {
     7             while (!ready)
     8                 Thread.yield();
     9             System.out.println(number);
    10         }
    11     }
    12 
    13     public static void main(String[] args) {
    14         new ReaderThread().start();
    15         number = 42;
    16         ready = true;
    17     }
    18 }
    View Code
  • 非原子性的64位操作:对于非volatile类型的long和double变量,JVM允许将64位的读操作或者写操作分解为两个32位操作。当读取一个非volatile类型的long变量时,如果对该变量的读操作和写操作在不同的线程中,可能读取的是A的高32位,B的低32位。
  • 如果对不同的锁进行同步,不能实现线程安全
    @NotThreadSafe
    class BadListHelper <E> {
        public List<E> list = Collections.synchronizedList(new ArrayList<E>());
    
        public synchronized boolean putIfAbsent(E x) {
            boolean absent = !list.contains(x);
            if (absent)
                list.add(x);
            return absent;
        }
    }
    
    @ThreadSafe
    class GoodListHelper <E> {
        public List<E> list = Collections.synchronizedList(new ArrayList<E>());
    
        public boolean putIfAbsent(E x) {
            synchronized (list) {
                boolean absent = !list.contains(x);
                if (absent)
                    list.add(x);
                return absent;
            }
        }
    }
    View Code

     

posted @ 2021-01-09 15:23  苏黎世湖畔  阅读(130)  评论(0)    收藏  举报