Java线程同步:synchronized锁住的是代码还是对象

所以我们在用synchronized关键字的时候,能缩小代码段的范围就尽量缩小,能在代码段上加同步就不要再整个方法上加同步。这叫减小锁的粒度,使代码更大程度的并发。原因是基于以上的思想,锁的代码段太长了,别的线程是不是要等很久,等的花儿都谢了。当然这段是题外话,与本文核心思想并无太大关联。

  再看上面的代码,每个线程中都new了一个Sync类的对象,也就是产生了三个Sync对象,由于不是同一个对象,所以可以多线程同时运行synchronized方法或代码段。

  为了验证上述的观点,修改一下代码,让三个线程使用同一个Sync的对象。

class MyThread extends Thread {

 private Sync sync;

 public MyThread(Sync sync) {   this.sync = sync;  }

 public void run() {   sync.test();  } }

public class Main {

 public static void main(String[] args) {   Sync sync = new Sync();   for (int i = 0; i < 3; i++) {    Thread thread = new MyThread(sync);    thread.start();   }  } }

  运行结果:

  test开始..   test结束..   test开始..   test结束..   test开始..   test结束..

  可以看到,此时的synchronized方法和synchronized代码段就都起了作用。

  那么,如果真的想锁住这段代码,要怎么做?也就是,如果还是最开始的那段代码,每个线程new一个Sync对象,怎么才能让test方法不会被多线程执行。

  解决也很简单,只要锁住同一个对象不就行了。例如,synchronized后的括号中锁一个static final对象,这样就行了。这样是没问题,但是,比较多的做法是让synchronized锁这个类对应的Class对象。

class Sync {

 public void test() {   synchronized (Sync.class) {    System.out.println("test开始..");    try {     Thread.sleep(1000);    } catch (InterruptedException e) {     e.printStackTrace();    }    System.out.println("test结束..");   }  } }

class MyThread extends Thread {

 public void run() {   Sync sync = new Sync();   sync.test();  } }

public class Main {

 public static void main(String[] args) {   for (int i = 0; i < 3; i++) {    Thread thread = new MyThread();    thread.start();   }  } }

  运行结果:

  test开始..   test结束..   test开始..   test结束..   test开始..   test结束..

  上面代码用synchronized(Sync.class)实现了全局锁的效果。

  最后说说static synchronized,实际上static方法可以直接类名加方法名调用,方法里面没有this这个概念,所以,static synchronized方法也相当于全局锁,相当于锁住了代码段。

原文地址:https://www.cnblogs.com/heartstage/p/3409712.html