synchronized锁的介绍

synchronized锁的使用

synchronized可以使用在方法和代码块中, 使用的方式不同锁代表的含义不同, 下面将从几个方面进行介绍.

  • 普通方法
  • 静态方法
  • 代码块synchronized(this)
  • 代码块synchronized(*.class)

结论

  • 在使用synchronized关键字中锁主要分为两类, 一种是对象锁, 另一种类锁
  • 普通加锁方法和synchronized(this)都是对象锁, 静态加锁方法和synchronized(*.class)都是类锁
  • 对象锁: 同一对象持有锁, 相同对象等待, 其他对象不受影响; 不同对象持有锁, 互不影响.
  • 类锁: 类锁时, 只要该类的对象持有锁, 无论是否为同一对象访问静态同步方法时都等待, 访问非静态同步方法不受影响.
  • 对象锁和类锁互相不影响

测试代码及过程

package com.liuzhihang.tool.sync;

/**
 * @author liuzhihang
 * @date 2018/7/11 16:25
 */
public class SyncMainTest {

    public static void main(String[] args) {
        SyncTest syncTest1 = new SyncTest();
        // SyncTest syncTest2 = new SyncTest();
        new Thread(() -> syncTest1.methodA(), "线程 01 ").start();
        new Thread(() -> syncTest1.methodB(), "线程 02 ").start();

    }
}


class SyncTest {

    void methodA() {

        System.out.println(Thread.currentThread().getName() + "start");
        try {
            System.out.println(Thread.currentThread().getName() + "sleep");
            Thread.sleep(500);
        } catch (InterruptedException e) {
        }
        System.out.println(Thread.currentThread().getName() + "end");
    }

    void methodB() {

        System.out.println(Thread.currentThread().getName() + "start");
        try {
            System.out.println(Thread.currentThread().getName() + "sleep");
            Thread.sleep(300);
        } catch (InterruptedException e) {
        }
        System.out.println(Thread.currentThread().getName() + "end");
    }

}

以上为一个简单的测试代码, 指使用两个线程分别调用两个方法, 通过打印结果可以看出顺序是乱序的, 其中线程的 start() 顺序并不代表线程的执行顺序, 在下面测试中假设是 “线程01” 先执行.

1.A B 方法分别添加synchronized关键字 + 同一对象

class SyncTest {
    synchronized void methodA() {
        // ...
    }
    synchronized void methodB() {
        // ...
    }

}

结论: 方法 A 阻塞, 方法 B 等待 A 执行完毕后才继续执行.

2.A B 方法分别添加synchronized关键字 + 不同对象

public class SyncMainTest {

    public static void main(String[] args) {
        SyncTest syncTest1 = new SyncTest();
        SyncTest syncTest2 = new SyncTest();
        new Thread(() -> syncTest1.methodA(), "线程 01 ").start();
        new Thread(() -> syncTest2.methodB(), "线程 02 ").start();

    }
}
class SyncTest {
    synchronized void methodA() {
        // ...
    }
    synchronized void methodB() {
        // ...
    }

}

结论: 方法 A 阻塞, 方法 B 不受影响.

3.A 方法分别添加synchronized关键字 B方法不添加

class SyncTest {
    synchronized void methodA() {
        // ...
    }
    void methodB() {
        // ...
    }

}

结论: 方法 A 阻塞, 方法 B 不受影响.

4.A B 方法分别添加 static synchronized + 不同对象

public class SyncMainTest {

    public static void main(String[] args) {
        SyncTest syncTest1 = new SyncTest();
        SyncTest syncTest2 = new SyncTest();
        new Thread(() -> syncTest1.methodA(), "线程 01 ").start();
        new Thread(() -> syncTest2.methodB(), "线程 02 ").start();

    }
}
class SyncTest {
    static synchronized void methodA() {
        // ...
    }
    static synchronized void methodB() {
        // ...
    }

}

结论: 方法 A 阻塞, 方法 B 等待 A结束后继续执行.

5.A 方法添加 static synchronized, B 方法添加 synchronized + 不同对象

public class SyncMainTest {

    public static void main(String[] args) {
        SyncTest syncTest1 = new SyncTest();
        SyncTest syncTest2 = new SyncTest();
        new Thread(() -> syncTest1.methodA(), "线程 01 ").start();
        new Thread(() -> syncTest2.methodB(), "线程 02 ").start();

    }
}
class SyncTest {
    static synchronized void methodA() {
        // ...
    }
    synchronized void methodB() {
        // ...
    }

}

结论: 方法 A 阻塞, 方法 B 不受影响.

6.A B 方法内添加 synchronized(this)

class SyncTest {
    void methodA() {
        synchronized (this) {
            // ...
        }
    }
    void methodB() {
        synchronized (this) {
            // ...
        }
    }

}

结论: 同一对象 A 阻塞 B等待, 不同对象 A阻塞 B不受影响

7.A B 方法内添加 synchronized(SyncTest.class)

class SyncTest {
    void methodA() {
        synchronized (SyncTest.class) {
            // ...
        }
    }
    void methodB() {
        synchronized (SyncTest.class) {
            // ...
        }
    }

}

结论: 同一/不同对象 A 阻塞 B等待

8.A 方法内添加 synchronized(SyncTest.class), B 方法内添加 synchronized(this)

class SyncTest {
    void methodA() {
        synchronized (SyncTest.class) {
            // ...
        }
    }
    void methodB() {
        synchronized (this) {
            // ...
        }
    }

}

结论: 同一/不同对象 A 阻塞 B不受影响

9.A 方法内添加 synchronized(SyncTest.class), B 方法内添加 synchronized(OtherObj)

class SyncTest {

    private String string = "lock";

    void methodA() {
        synchronized (SyncTest.class) {
            // ...
        }
    }
    void methodB() {
        synchronized (string) {
            // ...
        }
    }

}

结论: 同一/不同对象 A 阻塞 B不受影响


   转载规则


《synchronized锁的介绍》 liuzhihang 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录