类锁和对象锁的介绍

类锁:
可以锁住一个类里面被synchronized修饰的静态方法,他是全局统一的,当有多个线程访问多个实例的时候,如果这个时候一个线程使用了类锁,那么其他的线程如果执行到了被synchronized修饰的静态方法的时候就会进入等待
对象锁:
可以锁住一个类里面被synchronized修饰的普通方法,他不是全局统一的,当有多个线程访问多个对象的时候,这个时候线程1锁住了对象1,那么对于对象2来说是没有任何影响的,他们之间互不干扰,只有当线程3访问对象1的被synchronized修饰的普通方法的时候线程3会进入等待
下面是代码演示

对象锁:

一个对象,三个线程的时候

package com.thread;

import java.util.concurrent.TimeUnit;

public class SynTest {
    public static void main(String[] args) {
        A a = new A();
        new Thread(() ->{
            a.method01();   //A.method01();
        }).start();
        new Thread(() ->{
            //为了保证先让程序执行 a.method01();方法,这里延时100ms
            try {
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            a.method02(); A.method02();
        }).start();

        new Thread(() ->{
            //为了保证先让程序执行 a.method01();方法,这里延时100ms
            try {
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            a.method03(); A.method02();
        }).start();
    }
}

class A{

    public synchronized void method01(){
        //时停500ms
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("我是方法1");
    }

    public synchronized void method02(){
        System.out.println("我是方法2");
    }

    public synchronized static void method03(){
        System.out.println("我是方法3");
    }
}

最后输出结果
在这里插入图片描述
最后执行结果是秒打印出方法3,然后过了3秒之后先打印了方法1在打印了方法2。
这里程序最早执行的是方法1,刚进入方法1的时候A的对象锁会被锁住,这个时候所有被synchronized修饰的普通方法都会被锁住,当有线程想执行这些方法的时候就会在方法外面阻塞,等里面的线程从方法里面出去之后才会进入执行。
这里的方法3是秒打印的,说明方法3没有被对象锁阻塞。对象锁无法锁静态方法

两个对象两个线程的时候

package com.thread;

import java.util.concurrent.TimeUnit;

public class SynTest {
    public static void main(String[] args) {
        A a = new A();
        A a1 = new A();
        new Thread(() ->{
            a.method01();
        }).start();
        new Thread(() ->{
            //为了保证先让程序执行 a.method01();方法,这里延时100ms
            try {
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            a1.method02();
        }).start();
    }
}

class A{

    public synchronized void method01(){
        //时停3s
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("我是方法1");
    }

    public synchronized void method02(){
        System.out.println("我是方法2");
    }
}

输出结果:
在这里插入图片描述
秒打印了我是方法2,然后打印了方法1,这就说明这里执行的a1.method02();没有被a.method01();阻塞,因为他们是两个对象,两个对象之间的对象锁互不干扰

类锁

一个对象三个线程的时候

package com.thread;

import java.util.concurrent.TimeUnit;

public class SynTest {
    public static void main(String[] args) {
        A a = new A();
        new Thread(() ->{
            a.method01();   //A.method01();
        }).start();
        new Thread(() ->{
            //为了保证先让程序执行 a.method01();方法,这里延时100ms
            try {
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            a.method02(); A.method02();
        }).start();

        new Thread(() ->{
            //为了保证先让程序执行 a.method01();方法,这里延时100ms
            try {
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            a.method03(); A.method02();
        }).start();
    }
}

class A{

    public synchronized static void method01(){
        //时停500ms
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("我是方法1");
    }

    public synchronized static void method02(){
        System.out.println("我是方法2");
    }

    public synchronized void method03(){
        System.out.println("我是方法3");
    }
}

执行结果:
在这里插入图片描述
秒打印了方法3,然后过了3秒打印了方法1和方法2
这里程序最先执行的是方法1,方法1是被synchronized修饰的静态方法,当有线程执行这个方法的时候,这个对象的类锁就会被锁住,所有的被synchronized修饰的静态方法都会被锁住,当有线程想执行这些方法的时候,就会阻塞,所以方法2一直等到方法1执行完之后才执行,等了3s
这里方法3秒打印了出来,说明方法3没有被类锁锁住,也就是说类锁对于非静态方法无效

两个线程两个对象的时候

package com.thread;

import java.util.concurrent.TimeUnit;

public class SynTest {
    public static void main(String[] args) {
        A a = new A();
        A a1 = new A();
        new Thread(() ->{
            a.method01();   //A.method01();
        }).start();

        new Thread(() ->{
            //为了保证先让程序执行 a.method01();方法,这里延时100ms
            try {
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            a1.method02(); A.method02();
        }).start();

    }
}

class A{

    public synchronized static void method01(){
        //时停500ms
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("我是方法1");
    }

    public synchronized static void method02(){
        System.out.println("我是方法2");
    }
}

执行结果:
在这里插入图片描述
等了3s之后打印出了方法1和方法2,说明方法2被阻塞了
程序还是先执行的a.method01();这个方法,当线程1执行这个方法的时候类锁会触发,所有的被synchronized修饰的静态方法都会被锁住。

类锁和对象锁代码块的写法

		//对象锁
        synchronized (this){
            
        }
        
        //类锁
        synchronized (A.class){
            
        }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值