zoukankan      html  css  js  c++  java
  • 《java并发编程实战》(一)

    今天在看《java并发编程实战》时,书中第23页有一句话,有点是不很理解  “虽然synchronized方法可以确保当个操作的原子性,但如果要把多个操作合并为一个复合操作,还是需要额外的加锁机制”,网上找了很多,但发现都是他们的读书笔记,就直接把这段话记录了下来,个人愚钝,理解不了,后来找到了一篇博客:Vector 是线程安全的?,看完感觉写得很不错,由此copy过来做记录。

    或许,大家经常也碰到类似的问题:Vector 与 ArrayList 的区别?
    好多人一拍脑门就出:Vector 是线程安全的 (在任何情况下都是)。。。

    原因可能是因为 Vector 的所有方法加上了 synchronized 关键字,从而保证访问 vector 的任何方法都必须获得对象的 intrinsic lock (或叫 monitor lock),也即,在vector内部,其所有方法不会被多线程所访问。
    但是,以下代码呢:

    if (!vector.contains(element)) 
        vector.add(element); 
        ...
    }

    这是经典的 put-if-absent 情况,尽管 contains, add 方法都正确地同步了,但作为 vector 之外的使用环境,仍然存在  race condition: 因为虽然条件判断 if (!vector.contains(element))与方法调用 vector.add(element);  都是原子性的操作 (atomic),但在 if 条件判断为真后,那个用来访问vector.contains 方法的锁已经释放,在即将的 vector.add 方法调用 之间有间隙,在多线程环境中,完全有可能被其他线程获得 vector的 lock 并改变其状态, 此时当前线程的vector.add(element);  正在等待(只不过我们不知道而已)。只有当其他线程释放了 vector 的 lock 后,vector.add(element); 继续,但此时它已经基于一个错误的假设了。

    单个的方法 synchronized 了并不代表组合(compound)的方法调用具有原子性,使 compound actions  成为线程安全的可能解决办法之一还是离不开intrinsic lock (这个锁应该是 vector 的,但由 client 维护):

    // Vector v = ...
        public  boolean putIfAbsent(E x) {
        synchronized(v) { 
                boolean absent = !contains(x); 
                if (absent) { 
                    add(x);
                } 
            }
            return absent; 
       }
            


    所以,正确地回答那个“愚蠢”的问题是:
    Vector 和 ArrayList 实现了同一接口 List, 但所有的 Vector 的方法都具有 synchronized 关键修饰。但对于复合操作,Vector 仍然需要进行同步处理。 

    这样做的后果,Vector 应该尽早地被废除,因为这样做本身没有解决多线程问题,反而,在引入了概念的混乱的同时,导致性能问题,因为 synchronized 的开销是巨大的:阻止编译器乱序,hint for 处理器寄存一/二级缓存。。。

    原文出处:https://blog.csdn.net/xdonx/article/details/9465489

  • 相关阅读:
    c++字符串排序
    JAVA实现四则运算的简单计算器
    JAVA图形小动画之简单行星运动
    JAVA多线程编程
    ege图形库之简单贪吃蛇(c++)
    ege图形库之动画排序
    mysql 性能优化方案
    MYSQL 优化常用方法
    [手把手教你] 用Swoft 搭建微服务(TCP RPC)
    php有效防止同一用户多次登录
  • 原文地址:https://www.cnblogs.com/Guhongying/p/12817252.html
Copyright © 2011-2022 走看看