美文网首页
记:我理解的 Synchronized

记:我理解的 Synchronized

作者: 爱吃板栗的小女孩 | 来源:发表于2018-11-27 09:56 被阅读91次

    synchronized:当有多个线程一起访问某个方法时,synchronized可以保证同一时刻,只有一个线程可以访问,直到他访问结束,其他线程才可以访问,避免了线程安全问题。也可被称为互斥锁,也就是说当一个共享数据被当前正在访问的线程加上互斥锁后,在同一个时刻,其他线程只能处于等待的状态,直到当前线程处理完毕释放该锁。
    就好像在地铁站在人工充值前,大家排队等待。只有前面的人办理完成后,下一个人才可以上前办理业务
    参考于:
    讲的很通透https://blog.csdn.net/javazejian/article/details/72828483#synchronized%E4%BD%9C%E7%94%A8%E4%BA%8E%E5%AE%9E%E4%BE%8B%E6%96%B9%E6%B3%95
    例子很好 https://www.cnblogs.com/QQParadise/articles/5059824.html

    synchronized主要有3种应用方式:
    (1)修饰实例方法
    (2)修饰静态方法
    (3)修饰代码块

    第一种情况:修饰实例方法

    class A {
    public synchronized void a() { }
    public synchronized void b() {
    } }
    然后创建两个对象
    A a1 = new A();
    A a2 = new A(); 
    然后在两个线程中并发访问如下代码: Thread1 Thread2 a1.a(); a2.a();
    

    这种情况下,不能保证同步。此时的synchronized修饰的是实例方法,这种情况,当前线程的锁便是实例对象。而此时我们分别创建两个A的实例对象,a1和a2,即代表我们有两个线程锁。所以此时我们并不能保证是同步的。但是此时A中的a()和b(),若分别调用a()和b(),b则会在a执行完之后再执行,因为此时的锁是同一个实例。但是还是可以访问该实例对象的其他非synchronized方法。

    第二种情况:修饰静态方法

    class A {
      public static synchronized void a() { }
      public static synchronized void b() { }
    }
    

    若把A改成这种定义,是会同步的。static修饰的方法属于类,他的锁对应的也是类对象。但此时若增加一个public synchronized void c() { },这个方法是不会产生互斥现象,可以被其他线程调用,因为它是属于实例,他的锁和类方法锁不是同一个。

    第三种情况:修饰代码块

    往往有可能会有一大段代码,但是我们只需要保证其中的部分代码是同步即可

    //this:当前实例对象锁
    synchronized(this){
      ...
    }
    
    //class:当前类的锁
    synchronized(Test.class){
       ...
    }
    
    

    总而言之,我们即可以知道
    对于实例方法(非static修饰),互斥锁锁住的是当前实例对象。所以创建多个实例,互斥锁就有多个。
    对于类方法(static修饰),互斥锁锁住的是当前对应的类对象。由于无论创建多少个实例,类对象只有1个,所以这个情况下的互斥锁只有1个。

    相关文章

      网友评论

          本文标题:记:我理解的 Synchronized

          本文链接:https://www.haomeiwen.com/subject/dewbqqtx.html