zoukankan      html  css  js  c++  java
  • java面试-synchronized底层实现机制

    一、synchronized的三种应用方式

    1、修饰实例方法,锁是当前实例对象,进入同步代码前要获得当前实例的锁

    /**
     * synchronized修饰实例方法,当前线程的锁是实例对象accountingSync
     * 当一个线程正在访问一个对象的synchronized实例方法,那么其他线程不能访问该对象的其他synchronized方法
     * 一个对象只有一把锁
     */
    public class AccountingSync implements Runnable {
    
        static AccountingSync accountingSync = new AccountingSync();
        //共享资源
        static int i = 0;
        static int j = 0;
    
        public synchronized void increase() {
            i++;
        }
    
        @Override
        public void run() {
            for(int i =0;i<1000000;i++){
                synchronized (this){
                    increase();
                }
            }
        }
    
    
        public static void main(String[] args) throws InterruptedException {
            Thread thread1 = new Thread(accountingSync);
            Thread thread2 = new Thread(accountingSync);
            thread1.start();
            thread2.start();
            thread1.join();
            thread2.join();
            System.out.println(i);
        }
    }  
    /**
     * thread1访问实例对象obj1的synchronized方法,thread2访问实例对象obj1的synchronized方法
     * 这样是允许的,因为两个实例对象锁并不相同。
     * 此时如果两个线程操作数据非共享,线程安全有保证,如果数据共享,线程安全无法保证
     *
     */
    public class AccountingSyncBad implements Runnable {
    
        static int i = 0;
    
        public synchronized void increase() {
            i++;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 1000000; i++) {
                increase();
            }
        }
    
    
        public static void main(String[] args) throws InterruptedException{
            //new新实例
            Thread thread1 = new Thread(new AccountingSyncBad());
            //new新实例
            Thread thread2 = new Thread(new AccountingSyncBad());
            thread1.start();
            thread2.start();
            thread1.join();
            thread2.join();
            System.out.println(i);
        }
    }   

    2、修饰静态方法,锁是当前类的 class对象,进入同步代码前要获得当前类对象的锁 

    public class AccountingSyncClass implements Runnable{
    
        static int i = 0;
    
        /**
         * synchronized作用于静态方法,锁是当前class对象
         */
        public static synchronized void increase() {
            i++;
        }
    
        /**
         *  increase4Obj方法是实例方法,其对象锁是当前实例对象,
         *  如果别的线程调用该方法,将不会产生互斥现象,毕竟锁对象不同,
         *  但我们应该意识到这种情况下可能会发现线程安全问题(操作了共享静态变量i)。
         */
        public synchronized void increase4Obj(){
            i++;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 1000000; i++) {
                increase();
    //            increase4Obj();
            }
        }
    
    
        public static void main(String[] args) throws InterruptedException{
            //new新实例
            Thread thread1 = new Thread(new AccountingSyncClass());
            //new新实例
            Thread thread2 = new Thread(new AccountingSyncClass());
            thread1.start();
            thread2.start();
            thread1.join();
            thread2.join();
            System.out.println(i);
        }
    }  

    3、修饰代码块

    synchronized(this) 锁是当前实例对象,
    synchronized(AccountingSync.class) 锁是class对象

    二、synchronized代码块底层原理

    synchronized代码块是由一对monitorenter和monitorexit指令实现的,Monitor对象是同步的基本实现单元。

    现代java虚拟机对sychronized进行了优化,引入了偏斜锁、轻量级锁、重量级锁

    三、java虚拟机对Synchronized的优化

    JVM优化synchronized运行的机制,当JVM检测到不同的竞争情况时,会自动切换到适合的锁实现

    1、当没有竞争出现时,默认会使用偏斜锁JVM 会利用 CAS操作,在对象头上的Mark Word部分设置线程ID,以表示这个对象偏向于当前线程,所以并不涉及真正的互斥锁。这样做的假设是基于在很多应用场景中,大部分对象生命周期中最多会被一个线程锁定,使用偏斜锁可以降低无竞争开销。

    2、有竞争出现时,当有另外的线程试图锁定某个已经被偏斜锁锁定的对象,jvm就会撤销revoke偏斜锁,并切换到轻量级锁。轻量级锁依赖CAS操作Mark Word来试图获取锁,如果成功,就使用轻量级锁,否则继续升级未重量级锁

    PS:锁降级也是存在的,当JVM进入SafePoint安全点的时候,会检查是否有闲置的Monitor,然后试图进行降级。

  • 相关阅读:
    Centos-706-在Win10中共享目录然后在Linux中访问
    Centos-706-在Linux中共享目录然后在Win10中访问
    Centos-706-配置文件
    Centos-706-daemon.json启用hosts后无法启动
    Centos-706-Docker开启远程访问
    Centos-706-Docker镜像-生成以及推送
    Centos-706-固定IP设置
    jquery.chosen.js实现模糊搜索
    Mysql索引分析:适合建索引?不适合建索引?【转】
    查看 Apache并发请求数及其TCP连接状态【转】
  • 原文地址:https://www.cnblogs.com/wjh123/p/11408571.html
Copyright © 2011-2022 走看看