java并发编程中锁的对象有哪几种?

我们都知道在并发编程学习中锁的概念和使用是必须要学会的,那这个锁到底锁住的是什么呢?它又是如何保证线程之间的并发?

参考:Java中Synchronized的用法(简单介绍)

锁的分类

  1. java中的锁分为对象锁和类锁
  2. 一个类可以有多个对象,所以一个类可以有多个对象锁
  3. 一个类只有一个class,所有一个类只能有一个类锁

锁的机制(以synchronized为例)

  1. 修饰一个代码块时,该代码块称为同步代码块,同一时刻只能有一个线程进入该同步代码块,锁住的是包含这个代码块的对象。
  2. 修饰一个普通方法时,该方法称为同步方法,同一时刻只能有一个线程进入该方法,锁住的是包含该方法的对象。
  3. 修饰一个静态方法时,同一时刻只能有一个线程进入该方法,锁住的是包含该方法的类对象。
  4. 修饰一个类,同一时刻只能有一个线程访问,锁住的是类对象。

对象锁

1. 修饰一个代码块
public class Synchronize {
    public static void main(String[] args) {
        Print print = new Print();
        new Thread(print::printThread).start();
        new Thread(print::printThread).start();
    }
}

class Print {
    public void printThread() {
        synchronized (this) {
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "正在执行");
        }
    }
}

执行结果:

Thread-0正在执行
Thread-1正在执行

一个线程访问一个对象中的synchronized(this)同步代码块时,其他试图访问该对象的线程将被阻塞。

注意:不同的对象拥有不同的对象锁,可能导致线程同步失败

public static void main(String[] args) {
        Print print1 = new Print();
        Print print2 = new Print();
        new Thread(print1::printThread).start();
        new Thread(print2::printThread).start();
    }

执行结果:

Thread-1正在执行
Thread-0正在执行
2. 修饰一个普通方法
public class Synchronize {
    public static void main(String[] args) {
        Print print = new Print();
        new Thread(print::printThread).start();
        new Thread(print::printThread).start();
    }
}

class Print {
    public synchronized void printThread() {
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "正在执行");
    }
}

synchronized修饰普通方法和修饰代码块类似,下面两种方式是等价的:

public synchronized void method(){
    ...
}
public void method(){
    synchronized (this){
		...
    }
}

当一个线程访问对象的synchronized修饰的代码块或方法时,另一个线程虽然不能访问synchronized修饰的作用域的代码,但可以访问其他的代码。

public class Synchronize {
    public static void main(String[] args) {
        Print print = new Print();
        new Thread(print::printThread).start();
        new Thread(print::printThread2).start();
    }
}

class Print {
    public synchronized void printThread() {
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "正在执行");
    }

    public void printThread2() {
        System.out.println(Thread.currentThread().getName() + "正在执行");
    }
}

执行结果:

Thread-1正在执行
Thread-0正在执行

上面两种方式就是对象锁的主要实现方法,对象锁可以有多个,不同的对象拥有各自的对象锁。

类锁

1. 修饰一个静态方法
public class Synchronize {
    public static void main(String[] args) {
        Print print1 = new Print();
        Print print2 = new Print();
        new Thread(()->print1.printThread()).start();
        new Thread(()->print2.printThread()).start();
    }
}

class Print {
    public synchronized static void printThread() {
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "正在执行");
    }
}

执行结果:

Thread-0正在执行
Thread-1正在执行

静态方法时属于类的,因此对静态方法使用synchronized修饰后锁住的就是class对象,而该类的每个实例对象都由该class构造而来。synchronized修饰的静态方法锁住的是这个类的所有对象。

2. 修饰一个类

synchronized还可作用于一个类

public class Synchronize {
    public static void main(String[] args) {
        Print print = new Print();
        new Thread(print::printThread).start();
        new Thread(print::printThread).start();
    }
}

class Print {
    public void printThread() {
        synchronized (this.getClass()){
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "正在执行");
        }
    }
}

这种形式和修饰静态方法是一样的,因为class对象只有一个,该类的所有对象都共用一把锁。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值