java多线程与并发(三)——Java并发机制的底层实现原理

学习《java并发编程的艺术》笔记:

Java代码在编译后是Java字节码,字节码被类加载到JVM里,JVM执行字节码,最终转换为汇编指令在CPU上执行。
Java中所使用的并发机制依赖于JVM的实现和CPU的指令。

1、volatile
https://blog.csdn.net/u010843421/article/details/78059702
2、synchronized
利用synchronized实现同步的基础:java中的每一个对象都可以作为锁。具体表现为三种形式:
-普通同步方法,锁是当前实例对象
-静态同步方法,锁是当前类的Class对象
-同步方法块,锁是Synchronized括号里配置的对象
Synchronized在JVM里的实现原理:
JVM基于进入和退出Monitor对象来实现方法同步和代码块同步——代码块同步是monitorenter和monitorexit指令实现的;方法同步可以使用这两个指令实现,也可以使用另一种方式实现。

monitorenter指令是在编译后插入到同步代码块的开始位置,而monitorexit是插入大哦方法结束处或异常处。任何对象都有一个monitor对象与之对应。

无锁–>偏向所–>轻量级所–>重量级锁(只能升级,为了提高获得锁和释放锁的效率)
3、原子操作的实现原理
CAS(Compare and Swap):比较并交换
原子操作(atomic operation):不可被中断的一个或一系列操作

处理器实现原子操作的方法:
1)通过总线锁保证原子性
2)通过缓存锁定保证原子性
有两种情况处理器不使用缓存锁定:
1)操作数据不能被缓存在处理器内部或操作的数据跨多个缓存行时,处理器使用总线锁定
2)处理器不支持缓存锁定

Java中实现原子操作的方式:
1)循环CAS实现原子操作:
JVM利用了处理器提供的CMPXCHG指令实现的。自旋CAS实现的基本思路就是循环进行CAS操作直到成功为止。
示例:基于CAS线程安全的计数器方法safeCount和一个非线程安全的计数器count

public class Counter {
    private AtomicInteger atomicI=new AtomicInteger(0);//AtomicInteger用原子方式更新的int值
    private int i=0;

    /**
     * 使用CAS实现线程安全计数器
     */
    private void safeCount(){
        for(;;){
            int i=atomicI.get();
            boolean suc=atomicI.compareAndSet(i,++i);
            if(suc){
                break;
            }
        }
    }

    /**
     * 非线程安全计数器
     */
    private void count(){
        i++;
    }
    public static void main(String[] args){
        final Counter cas=new Counter();
        List<Thread> ts=new ArrayList<Thread>(600);
        long start=System.currentTimeMillis();
        for(int j=0;j<100;j++){
            Thread t=new Thread(new Runnable(){
                @Override
                public void run(){
                    for(int i=0;i<100;i++){
                        cas.count();
                        cas.safeCount();
                    }
                }
            });
            ts.add(t);
        }
        for(Thread t:ts){
            t.start();
        }
        //等待所有线程执行完毕
        for(Thread t:ts){
            try{
                t.join();
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
        System.out.println(cas.i);
        System.out.println(cas.atomicI.get());
        System.out.println(System.currentTimeMillis()-start);
    }
}

运行结果:
9984
10000
14

JVM内部实现了很多锁机制:偏向所、轻量级锁和互斥锁,除了偏向锁,其他都用了循环CAS,即当一个线程想进入同步块的时候使用循环CAS的方式获取锁,退出同步块的时候使用循环CAS释放锁。

小节:JAVA中大部分容器和框架都依赖于volatile和原子操作的实现原理。深入了解对并发编程有帮助。

猜你喜欢

转载自blog.csdn.net/u010843421/article/details/80836233