15.同步锁的类型有哪些

 

同步锁的类型有哪些

 引言

本节介绍一个和同步相关的知识点,同步锁,什么是同步锁?

我们先来看一下它的概念,同步锁是为了保证每个线程都能正常执行原子不可更改操作,同步监听对象/同步锁/同步监听器/互斥锁的一个标记锁。

我们这里先要说明一下,同步监听对象/同步锁/同步监听器/互斥锁,他们表示的都是同一个意思,那就是同步锁。

上一节卖票的例子

这整段话太术语了,我们还是来结合上一节卖票的例子来说,在上一节买票的例子中,他一共出现了两个问题,一个是重复票,一个是错票。出现重复票是因为三个线程同时查询余票,都发现10号票没人卖,所以每个线程都卖了一张10号票。

为了解决这个问题,我们使用了同步。但是即使我们使用了同步,还是出现了问题,出现了错票,

 

出现错票是因为同步代码块内部没有判断是否还有余票,所以呢就导致卖票代码被执行了三遍,于是就出现了错票。为了解决这个问题,我们使用了同步代码块内外双重判断,这才把重复票和售票彻底解决。

什么是同步锁

同一时刻最多只有一个线程执行同步代码,那么这个就是同步锁的作用。

同步锁的类型

下面我们来看看什么样的类型才可以成为同步锁呢?一共有两种类型,一个是对象类型,还有一个是类类型。 

对象类型

对象类型就是new出来的对象,比如说我们自定义的一个普通的Java类student,直接new一个student对象,然后它就可以成为一个同步锁,你再比如说我们new obj的对象,那么这个obj的对象就可以成为这个同步锁,再比如说这是关键词this。他为什么可以?因为他指代的就是当前对象

 类类型

我们再来看类类型,类类型就是类名点class。你比如说student.class,Object.class,他们都可以当做是同步锁。

 代码实例

下面我们来看一些具体的代码实例,比如这里的同步锁是student的对象,

还有这里的同步锁object的对象

以及this锁,

这个得结合具体的对象来看。 

 

同步代码块

this

student

比如说student的类,它里面有个setName方法,这个方法里面有一个同步代码块,它的同步锁是this,那么这个this指代的就是那个调用setName的student的对象。

package com.chenjie.executor.day15;

/**
 * packageName com.chenjie.executor.day15
 *
 * @author chenjie
 * @version JDK 8
 * @className Student (此处以class为例)
 * @date 2024/5/28
 * @description TODO
 */
public class Student {
    private static String name;

    public void setName(String name) {
        synchronized (this){
            if(null==this.name){
                this.name = name;
                System.out.println("setName="+name);
            }

        }
    }
}
SetNameTask
package com.chenjie.executor.day15;

/**
 * packageName com.chenjie.executor.day14
 *
 * @author chenjie
 * @version JDK 8
 * @className TicketTask (此处以class为例)
 * @date 2024/5/28
 * @description TODO
 */
public class SetNameTask implements Runnable {
    private Student student;

    public SetNameTask(Student student) {
        this.student = student;
    }

    @Override
    public  void run() {
        student.setName(Thread.currentThread().getName());


    }
}
main
package com.chenjie.executor.day15;


import com.chenjie.executor.day14.TicketTask2;

/**
 * packageName com.chenjie.executor.day09
 *
 * @author chenjie
 * @version JDK 8
 * @className Main1 (此处以class为例)
 * @date 2024/5/27
 * @description TODO
 */
public class Main {

    /**
     * 创建三个线程来跑这段代码
     * @param args
     */
    public static void main(String[] args) {
        Student student=new Student();
        SetNameTask task=new SetNameTask(student);
        Thread thread = new Thread(task,"thread");
        Thread thread1 = new Thread(task,"thread1");
        Thread thread2 = new Thread(task,"thread2");
        thread.start();
        thread1.start();
        thread2.start();

    }
}
打印结果
setName=thread

例如这个画红线的这个 Student对象,

new student

student类加方法
    public void setName0(String name) {
        synchronized (new Student()){
            if(null==this.name){
                this.name = name;
                System.out.println("setName="+name);
            }

        }
    }
打印结果
setName=thread

类类型

student
    public void setName1(String name) {
        synchronized (this.getClass()){
            if(null==this.name){
                this.name = name;
                System.out.println("setName="+name);
            }

        }
    }
打印结果
setName=thread

同步方法

student

    public synchronized void setName2(String name) {
            if(null==this.name){
                this.name = name;
                System.out.println("setName="+name);
            }


    }
打印结果
setName=thread

 

 类类型

类类型呢作为同步代码块的锁也是可以的,比如说student.class,

student

    public  static  synchronized void setName3(String name) {
        if(null==Student.name){
            Student.name = name;
            System.out.println("setName="+name);
        }


    }
打印结果
setName=thread

 

分类划分

好了,虚拟代码已经全部看完了。下面我们再来重新分一个类

如果我们按同步类型来分的话,

同步代码块的锁类型呢就有三个,分别是对象类型、this和类类型。 

同步方法的锁类型呢只有一个,那就是this。

静态同步方法的锁类型,也只有一个是类类型。

总结

最后我们来总结一下本节的内容。本节我们介绍了同步所的概念,同步所是为了保证每个线程都能正常执行原子不可更改操作,我们说了,同步监听对象/同步锁/同步监听器/互斥锁,他们都是同步锁。说的是一个意思。在实际开发中同步代码块,同步方法,静态同步方法,经常被使用到,所以各种锁类型也会经常被用到。

 

posted @ 2022-05-03 14:36  小陈子博客  阅读(169)  评论(0编辑  收藏  举报