zoukankan      html  css  js  c++  java
  • 谈谈synchronized

    为什么要用synchronized关键字:

      synchronized是java的一种内部锁,是一种排他锁,通常也被称为悲观锁,它能够保障原子性,可见性,有序性。

      当多个线程去调用同一个方法的时候,如果不用加synchronized锁,就可能出现线程不安全的问题。举个经典的例子,比如两夫妻一个用银行卡,一个用网银同时取同一个账户的钱,

    取钱这个操作在银行的后台肯定是一个方法,如果两方同时调用,很有可能造成取了两份的钱,这样肯定是不行的。

    synchronized的两种使用方式:

      1,synchronized加在方法上

    public class T {
    
        private int count = 10;
        
        public synchronized void m() {
            count--;
            System.out.println(Thread.currentThread().getName() + " count = " + count);
        }
    
    }

      2,synchronized代码块

    public class T {
    
        private int count = 10;
    
        public void m() {
            synchronized(this) {
                count--;
                System.out.println(Thread.currentThread().getName() + " count = " + count);
            }
        }
    
    }

    这里两种方式达到的效果是一样的,我们需要关注以下几点:

      1,synchronized锁,锁的是什么东西。其实是锁的一个对象,任意对象都可以(String常量,Integer,Long不能使用)。当一个线程拿到锁之后,其他的线程就只能等待当前线程执行完,

    并释放锁之后,才能拿到锁并执行。以此来保证线程的安全。

      2,这两种方式我们该用哪一种呢?实际开发中,我们应该用代码块的方式,为什么要加锁,通常都是需要访问共享变量才会加锁,一个方法中并不是所有代码都需要访问共享变量,

    其他的业务逻辑是不需要加锁的,所以代码块的方式可以提高程序的性能。

      3,synchronized是一种可重入的锁,什么意思呢,就是如果synchronized代码块中又调用了另外一个加锁的方法,本来如果锁没有释放,是不能拿到锁的。但是可重入锁是可以的,系统会自动识别。

    synchronized的底层实现:

      jdk早期的时候,synchronized的底层实现是重量级的,重量到可能需要到操作系统去申请锁的地步,所以造成synchronized的效率非常低。jdk1.6之后进行了改进,有了锁升级的概念。

    当我们访问synchronized的时候,HotSpot的实现是这样的,当第一个线程来访问的时候,先在锁对象的头上markword记录这个线程,实际上只要一个线程来访问的时候,是不会加锁的,

    只是记录这个线程ID,此时称之为偏向锁

      偏向锁如果有线程竞争的话,比如我第一个线程还没有释放锁,第二个线程又来了,就会自动升级为自旋锁,自旋锁的实现原理就是,线程会一直转圈等待获取锁,如果转圈十次之后,还没有获取到锁

    就自动升级为重量级锁

      所以说从效率方面来讲,CAS(后续文章会讲解)并不是一定就比synchronized锁的效率高,理解synchronized的底层实现,我们就可以得到如下结论:

    • 被锁住的代码,执行实际短,线程数量少的情况,用CAS。
    • 被锁住的代码,执行时间长,线程数量多的情况,用系统锁(synchronized内部锁和lock显示锁)。

      为什么这样说呢,假如我有1000个线程,用CAS自旋,那岂不是有999个线程会一直在旋转等待,这样是非常消耗资源的。

  • 相关阅读:
    【Codeforces 933A】A Twisty Movement
    【Codeforces 996B】World Cup
    【Codeforces 469B】Chat Online
    鼠标点击后的CSS3跑马灯效果
    CSS的相对定位和绝对定位
    CSS3制作的一款按钮特效
    单元测试小结
    JS对输入判断变化屏蔽中文输入法输入时连续触发事件的方法
    jquery的load方法
    MVC视图特性
  • 原文地址:https://www.cnblogs.com/liu-yi/p/12945137.html
Copyright © 2011-2022 走看看