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。
静态同步方法的锁类型,也只有一个是类类型。
总结
最后我们来总结一下本节的内容。本节我们介绍了同步所的概念,同步所是为了保证每个线程都能正常执行原子不可更改操作,我们说了,同步监听对象/同步锁/同步监听器/互斥锁,他们都是同步锁。说的是一个意思。在实际开发中同步代码块,同步方法,静态同步方法,经常被使用到,所以各种锁类型也会经常被用到。
本文来自博客园,作者:小陈子博客,转载请注明原文链接:https://www.cnblogs.com/cj8357475/p/16086033.html