您的位置:首页 > 其它

再聊聊 synchronized 关键字

2020-05-10 04:20 1196 查看

当synchronized关键字,有不少同学已经耳熟能详了,作为作为复习还是要巩固一下,因为面试常问这个东西。

第一个是多个线程去访问同一个资源的时候,对这个资源要上锁。为什么要上锁呢?访问某一段代码或者某临界资源的时候是需要有一把锁的概念的。

比如:我们对一个数字做递增,两个程序对它一块儿来做递增,递增就是把一个程序往上加1,如果两个线程共同访问的时候,第一个线程读它是0,然后把它加1,在自己线程内部内存里面算还没有写回去的时候,第二个线程读到了它还是0,加1再写回去,本来加了两次,但是还是1。

那么我们在对这个数字递增的过程中上把锁,就是说第一个线程对这个数字访问的时候是独占的,不允许别的线程来访问,不允许别的线程来对它进行计算,我必须加完1再释放锁,其他线程才能对它继续加。

实质上,这把锁并不是对数字进行锁定的,你可以任意指定,想锁谁就锁谁。

我第一个程序是这么写的,如果说你想上了把锁之后才能对count进行减减访问,你可以new一个Object,所以这里锁定就是0,当我拿到这把锁的时候才能执行这段代码。

/**
 * synchronized关键字
 * 对某个对象加锁
 * @author mashibing
 */

package com.mashibing.juc.c_001;

public class T {
  
  private int count = 10;
  private Object o = new Object();
  
  public void m() {
    synchronized(o) { //任何线程要执行下面的代码,必须先拿到o的锁
      count--;
      System.out.println(Thread.currentThread().getName() + " count = " + count);
    }
  }
  
}

我们来谈一下synchronized的一些特性。如果说你每次都定义一个锁的对象Object o,把它new出来,那加锁的时候太麻烦,每次都要new一个新的对象出来。所以呢,最简单的方式就是synchronized(this),锁定当前对象就行。

/**
 * synchronized关键字
 * 对某个对象加锁
 * @author mashibing
 */

package com.mashibing.juc.c_002;

public class T {
  
  private int count = 10;
  
  public void m() {
    synchronized(this) { //任何线程要执行下面的代码,必须先拿到this的锁
      count--;
      System.out.println(Thread.currentThread().getName() + " count = " + count);
    }
  }
  
}

如果你要是锁定当前对象,你也可以写成synchronized方法,这个和synchronized(this)是等值的。

/**
 * synchronized关键字
 * 对某个对象加锁
 * @author mashibing
 */

package com.mashibing.juc.c_003;

public class T {

  private int count = 10;
  
  public synchronized void m() { //等同于在方法的代码执行时要synchronized(this)
    count--;
    System.out.println(Thread.currentThread().getName() + " count = " + count);
  }
}

我明知道静态方法static是没有this对象的,你不需要new出一个对象来就能执行这个方法,但是如果这个上面加一个synchronized的话就表示synchronized(T.class),这里这个synchronized(T.class)锁的就是T类的对象。

/**
 * synchronized关键字
 * 对某个对象加锁
 * @author mashibing
 */

package com.mashibing.juc.c_004;

public class T {

  private static int count = 10;
  
  public synchronized static void m() { //这里等同于synchronized(FineCoarseLock.class)
    count--;
    System.out.println(Thread.currentThread().getName() + " count = " + count);
  }
  
  public static void mm() {
    synchronized(T.class) { //考虑一下这里写synchronized(this)是否可以?
      count --;
    }
  }

}

程序员Tony 原创文章 25获赞 174访问量 1万+ 关注 私信
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: