Java-并发-锁-synchronized之对象锁和类锁

Java-并发-锁-synchronized之对象锁和类锁

0x01 概述

1.1 更多信息

synchronized是java中最常用的一种锁机制,本篇文章主要介绍他的两种用途:类锁和对象锁。

关于synchronized的更多内容可以查看这篇文章: Java-并发-锁-synchronized

更多关于Java锁的信息,可参考文章:Java-并发-关于锁的一切

1.2 总览

几张图片转自图解Java多线程,作者 任何忧伤,都抵不过世界的美丽

1.2.1 实例方法

Java-并发-锁-synchronized之对象锁和类锁_第1张图片

1.2.2 静态方法

Java-并发-锁-synchronized之对象锁和类锁_第2张图片

1.2.3 代码块的同步

Java-并发-锁-synchronized之对象锁和类锁_第3张图片
用jstack查看,同一个监视器对象只允许有一个线程访问:
Java-并发-锁-synchronized之对象锁和类锁_第4张图片

1.2.4 实例方法的同步加上代码块this的同步

仍然针对同一个实例对象
Java-并发-锁-synchronized之对象锁和类锁_第5张图片

1.2.5 自定义监视器对象

Java-并发-锁-synchronized之对象锁和类锁_第6张图片

0x02 对象锁

synchronized作为对象锁时,用在非静态方法或非静态对象上,下面是示例:

	/**
     * 对象锁
     */
    public synchronized  void nonStaticMethodLock(){
        for(int i = 0 ; i< 5 ; i++){
            System.out.println(Thread.currentThread().getName()+" nonStaticMethodLock");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 对象锁
     */
    public void objectLock(){
        synchronized(this){
            for(int i = 0 ; i< 5 ; i++){
                System.out.println(Thread.currentThread().getName()+" objectLock");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

0x03 类锁

Java-并发-锁-synchronized之对象锁和类锁_第7张图片
类锁修饰方法、代码块的效果和对象锁是一样的,因为类锁只是一个抽象出来的概念,只是为了区别静态方法的特点。因为静态方法是所有对象实例共用的,所以对应synchronized修饰的静态方法的锁也是唯一的,所以抽象出来个类锁。

下面是代码示例:

/**
     * 类锁
     */
    public void classLock(){
        synchronized(Test3.class){
            for(int i = 0 ; i< 5 ; i++){
                System.out.println(Thread.currentThread().getName()+" classLock");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 类锁
     */
    public static synchronized  void staticMethodLock(){
        for(int i = 0 ; i< 5 ; i++){
            System.out.println(Thread.currentThread().getName()+" staticMethodLock");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

0x04 代码示例

下面是完整的代码示例,可以自行调试观察结果,加深理解:

package demos.concurrent.thread.synchronizedTest.objectAndMethodLock;

/**
 * Created by chengc on 2018/10/22.
 */
public class Test3 {
    private Object nonStaticLockObj = new Object();
    private static Object staticLockObj = new Object();
    private static Object staticLockObj2 = new Object();

    /**
     * 类锁
     */
    public void classLock(){
        synchronized(Test3.class){
            for(int i = 0 ; i< 5 ; i++){
                System.out.println(Thread.currentThread().getName()+" classLock");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 类锁
     */
    public static synchronized  void staticMethodLock(){
        for(int i = 0 ; i< 5 ; i++){
            System.out.println(Thread.currentThread().getName()+" staticMethodLock");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public void ordinaryMethod(){
        for(int i = 0 ; i< 5 ; i++){
            System.out.println(Thread.currentThread().getName()+" ordinaryMethod");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 对象锁
     */
    public synchronized  void nonStaticMethodLock(){
        for(int i = 0 ; i< 5 ; i++){
            System.out.println(Thread.currentThread().getName()+" nonStaticMethodLock");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 对象锁
     */
    public void thisObjectLock(){
        synchronized(this){
            for(int i = 0 ; i< 5 ; i++){
                System.out.println(Thread.currentThread().getName()+" thisObjectLock");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 对象锁
     */
    public void nonStaticObjectLock(){
        synchronized(nonStaticLockObj){
            for(int i = 0 ; i< 5 ; i++){
                System.out.println(Thread.currentThread().getName()+" nonStaticLockObj");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 对象锁
     */
    public void staticObjectLock(){
        synchronized(staticLockObj){
            for(int i = 0 ; i< 5 ; i++){
                System.out.println(Thread.currentThread().getName()+" staticLockObj");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 对象锁
     */
    public void staticObjectLock2(){
        synchronized(staticLockObj2){
            for(int i = 0 ; i< 5 ; i++){
                System.out.println(Thread.currentThread().getName()+" staticLockObj2");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        Test3 test1 = new Test3();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test1.classLock();
            }
        },"Thread1").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test1.nonStaticMethodLock();
            }
        },"Thread2").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test1.ordinaryMethod();
            }
        },"Thread3").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test1.staticMethodLock();
            }
        },"Thread4").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test1.thisObjectLock();
            }
        },"Thread5").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test1.nonStaticObjectLock();
            }
        },"Thread6").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test1.staticObjectLock();
            }
        },"Thread7").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                test1.staticObjectLock2();
            }
        },"Thread8").start();

    }
}

0x05 总结

通过以上代码调试,总结如下:

  1. 写在方法上的synchronized锁和写在代码块上用this修饰的对象锁同时只能有一个线程进入执行,但不影响其他方法执行
  2. 写在静态方法和代码块上用XXX.class修饰的为类锁,同时只能有一个线程进入执行,但不影响其他方法执行
  3. 用其他自己声明的对象作为对象锁修饰的方法或是代码块,互不影响
  4. 普通方法不受对象锁和类锁影响

关于synchronized的更多内容可以查看这篇文章: Java-并发-锁-synchronized

更多关于Java锁的信息,可参考文章:Java-并发-关于锁的一切

你可能感兴趣的:(java,并发)