百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术流 > 正文

“全栈2019”Java多线程第十七章:同步锁解析

citgpt 2024-08-01 13:32 11 浏览 0 评论

难度

初级

学习时间

30分钟

“全栈2019”Java多线程第十七章:同步锁解析

适合人群

零基础

开发语言

Java

开发环境

  • JDK v11
  • IntelliJ IDEA v2018.3

友情提示

  • 本教学属于系列教学,内容具有连贯性,本章使用到的内容之前教学中都有详细讲解。
  • 本章内容针对零基础或基础较差的同学比较友好,可能对于有基础的同学来说很简单,希望大家可以根据自己的实际情况选择继续看完或等待看下一篇文章。谢谢大家的谅解!

1.温故知新

在《“全栈2019”Java多线程第十六章:同步synchronized关键字详解》一章中介绍了synchronized关键字

现在我们来讲解同步代码块/方法中的同步锁

2.生活中的同步锁

在我们日常生活中,也有异步和同步的例子。下面,先来看一个异步的例子:如果把人看作是一个线程,把厕所看作是一个资源,人上厕所就是线程去访问资源。多个人就是多个线程,多个人上厕所就是多线程访问资源。

接下来,就展示了多个人去上同一个厕所,即多线程异步访问同一个资源

当然了,实际生活中,我们都是遵守秩序的好同学。我们多个人会排队一个一个地上厕所,即多线程同步访问同一个资源

例子中的同步锁是什么呢?

是门上的锁。

当进入厕所后,把门锁上,上完厕所时,把门打开。

当门被锁上后,后面的人就进不来,除非门里面的人开门,这就避免发生多个人同时上一个厕所的情况。

注意:上面例子中都是多个线程在访问同一个资源,会造成线程安全问题,所以需要同步。但是,单线程访问同一个资源或多线程访问各自的资源时,则不需要同步。

展示单线程访问同一资源情形:

展示多线程访问各自的资源情形:

3.同步对象

什么是同步对象?

在回答这个问题之前,我们需要借助同步代码块的定义来看:

可以看到的是写在紧跟synchronized关键字后面小括号里面的内容就是同步对象

下面通过示例代码来感受一下:

上述程序代码中的同步对象就是this

this我们知道代表的是实际调用该方法的当前对象。例如这里的ticketingTaskThread对象:

当然了,我们不光可以用this来作为同步对象,还可以使用任何一个Java对象来作为同步对象。

例如,我们这里可以使用String对象来作为同步对象:

再比如,使用Object对象来作为同步对象:

最后,我们也可以使用自定义Java对象来作为同步对象:

为什么所有Java对象都可以作为同步对象呢?

因为每个Java对象都有且只有一个同步锁,所以所有Java对象都可以作为同步对象

接下来,就来介绍什么是同步锁。

4.同步锁的定义

每个Java对象都有且只有一个同步锁,在任何时刻,最多只允许一个线程拥有这把锁,当消费者线程试图执行带有synchronized(this)标记的代码块时,消费者线程必需先获得this关键字引用的Stack对象的锁。

下面,我们分词解释+举例说明同步锁的定义。

例子是上一章中售票类的示例代码:

第一句,每个Java对象都有且只有一个同步锁

每个Java对象都有且只有一个同步锁”中的每个Java对象也就是包含了所有Java对象。

例如String、Object、自定义Java对象...等等。在上一小节讲解同步对象时也演示了这个问题。

每个Java对象都有且只有一个同步锁”中的有且只有一个同步锁说的是每个Java对象都有一个属于自己的同步锁,且这个同步锁只有一个。说明锁具有唯一性

第二句,在任何时刻,最多只允许一个线程拥有这把锁

正是因为锁的唯一性,所以只能有一个线程拥有这把锁。

就好比,三个人同时跑去洗手间,但每次只能进去一人,这个进去的人相当于拥有这把锁,进去以后呢,他会将门锁上,直到上完厕所出来,然后轮到后面要上厕所人。

在任何时刻,最多只允许一个线程拥有这把锁”这句话用“在任何时刻,最多只允许一个人进入洗手间”理解也不错,希望大家可以理解。

第三句,当消费者线程试图执行带有synchronized(this)标记的代码块时

当消费者线程试图执行带有synchronized(this)标记的代码块时”中的消费者线程指的是什么?

简单来说就是每一个线程都是消费者线程,大家理解为线程即可。

当消费者线程试图执行带有synchronized(this)标记的代码块时”中的synchronized(this)标记的代码块指的是什么?

synchronized(this)标记的代码块指的是同步代码块。

当然了,这里不应该只理解为同步代码块,毕竟还有同步方法。所以,这里综合指的是同步代码块和同步方法。

综上所述,“当消费者线程试图执行带有synchronized(this)标记的代码块时”的意思就是当线程执行同步代码块或同步方法时

第四句,消费者线程必需先获得this关键字引用的Stack对象的锁

将“消费者线程必需先获得this关键字引用的Stack对象的锁”中的消费者线程替换为线程,即“线程必需先获得this关键字引用的Stack对象的锁”。

线程必需先获得this关键字引用的Stack对象的锁”中的Stack对象指的是的堆栈中的对象。

综上所述,“消费者线程必需先获得this关键字引用的Stack对象的锁”意思就是线程必需先获得同步对象的锁。

综上所述

每个Java对象都有且只有一个同步锁,在任何时刻,最多只允许一个线程拥有这把锁,当消费者线程试图执行带有synchronized(this)标记的代码块时,消费者线程必需先获得this关键字引用的Stack对象的锁。”这句话说明以下几点:

  1. 同步需要有同步对象。
  2. 每个同步对象里面有且只有一个同步锁。
  3. 每个Java对象都可以是同步对象。
  4. 线程在执行同步代码块/方法时必需先获得同步锁。
  5. 最多只允许一个线程拥有这把同步锁。

别名

同步锁又被称为监视器

这里大家知道就行,叫什么都对,自己喜欢叫什么就叫什么。

5.静态/非静态方法里面的同步对象

上述程序代码中同步对象写的是this,该程序运行之所以没有报错是因为我们可以在非静态方法中使用this关键字,那么如果是在静态方法中呢?来修改上述程序代码试试:

这里我们改了两处。

第一处,我们将非静态方法改为了静态方法:

第二处,因为是静态方法,所以方法内部的成员变量也必须是静态的:

好,配合之前的Main类:

运行程序,执行结果:

错误信息:

文字版:

/Users/admin/Workspace/Java/Hello/src/lab/TicketingTaskThread.java

Error:(27, 23) java: 无法从静态上下文中引用非静态 变量 this

错误出现在TicketingTaskThread类的27行:

异常信息说“无法从静态上下文中引用非静态 变量 this”,通过前面Java基础知识的学习,我们知道非静态变量(实例变量/成员变量)只能被对象调用;静态变量(类变量)可以直接被类名调用。

故,这里需要一个新的同步对象来代替,它是什么呢?

它就是类对象。即类名.class任意类的类名都行。例如String.class、Object.class...等等。

接下来,修改我们的TicketingTaskThread类:

这里我们使用的类名是当前TicketingTaskThread类的名称。

Main类无需修改。

运行程序,执行结果:

从运行结果来看,程序没有任何问题。

综上所述

非静态方法中,同步代码块的同步对象可以是任意Java实例对象。

静态方法中,同步代码块的同步对象可以是任意Java类对象。

6.静态/非静态同步方法的同步对象

上一小节展示了静态/非静态方法里面的同步代码块中的同步对象各是什么,本小节来认识静态/非静态同步方法上的同步对象又是什么。

非静态同步方法:

非静态同步方法的同步对象是this

静态同步方法:

静态同步方法的同步对象是当前类的类名.class

例如上述程序代码中的静态同步方法的同步对象是TicketingTaskThread.class。

总结

  • 紧跟synchronized关键字后面小括号里面的内容就是同步对象。
  • 每个Java对象都有且只有一个同步锁,在任何时刻,最多只允许一个线程拥有这把锁,当消费者线程试图执行带有synchronized(this)标记的代码块时,消费者线程必需先获得this关键字引用的Stack对象的锁。
  1. 同步需要有同步对象。
  2. 每个同步对象里面有且只有一个同步锁。
  3. 每个Java对象都可以是同步对象。
  4. 线程在执行同步代码块/方法时必需先获得同步锁。
  5. 最多只允许一个线程拥有这把同步锁。
  • 同步锁又被称为监视器。
  • 非静态方法中,同步代码块的同步对象可以是任意Java实例对象。
  • 静态方法中,同步代码块的同步对象可以是任意Java类对象。
  • 非静态同步方法的同步对象是this。
  • 静态同步方法的同步对象是当前类的类名.class。

至此,Java中同步锁相关内容讲解先告一段落,更多内容请持续关注。

答疑

如果大家有问题或想了解更多前沿技术,请在下方留言或评论,我会为大家解答。

上一章

“全栈2019”Java多线程第十六章:同步synchronized关键字详解

下一章

“全栈2019”Java多线程第十八章:同步代码块双重判断详解

学习小组

加入同步学习小组,共同交流与进步。

  • 方式一:关注头条号Gorhaf,私信“Java学习小组”。
  • 方式二:关注公众号Gorhaf,回复“Java学习小组”。

全栈工程师学习计划

关注我们,加入“全栈工程师学习计划”。

版权声明

原创不易,未经允许不得转载!

相关推荐

js中arguments详解

一、简介了解arguments这个对象之前先来认识一下javascript的一些功能:其实Javascript并没有重载函数的功能,但是Arguments对象能够模拟重载。Javascrip中每个函数...

firewall-cmd 常用命令

目录firewalldzone说明firewallzone内容说明firewall-cmd常用参数firewall-cmd常用命令常用命令 回到顶部firewalldzone...

epel-release 是什么

EPEL-release(ExtraPackagesforEnterpriseLinux)是一个软件仓库,它为企业级Linux发行版(如CentOS、RHEL等)提供额外的软件包。以下是关于E...

FullGC详解  什么是 JVM 的 GC
FullGC详解 什么是 JVM 的 GC

前言:背景:一、什么是JVM的GC?JVM(JavaVirtualMachine)。JVM是Java程序的虚拟机,是一种实现Java语言的解...

2024-10-26 08:50 citgpt

使用Spire.Doc组件利用模板导出Word文档
  • 使用Spire.Doc组件利用模板导出Word文档
  • 使用Spire.Doc组件利用模板导出Word文档
  • 使用Spire.Doc组件利用模板导出Word文档
  • 使用Spire.Doc组件利用模板导出Word文档
跨域(CrossOrigin)

1.介绍  1)跨域问题:跨域问题是在网络中,当一个网络的运行脚本(通常时JavaScript)试图访问另一个网络的资源时,如果这两个网络的端口、协议和域名不一致时就会出现跨域问题。    通俗讲...

微服务架构和分布式架构的区别

1、含义不同微服务架构:微服务架构风格是一种将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级通信机制(通常用HTTP资源API)。这些服务围绕业务能力构建并...

深入理解与应用CSS clip-path 属性
深入理解与应用CSS clip-path 属性

clip-pathclip-path是什么clip-path 是一个CSS属性,允许开发者创建一个剪切区域,从而决定元素的哪些部分可见,哪些部分会被隐...

2024-10-25 11:51 citgpt

HCNP Routing&Switching之OSPF LSA类型(二)
  • HCNP Routing&Switching之OSPF LSA类型(二)
  • HCNP Routing&Switching之OSPF LSA类型(二)
  • HCNP Routing&Switching之OSPF LSA类型(二)
  • HCNP Routing&Switching之OSPF LSA类型(二)
Redis和Memcached的区别详解
  • Redis和Memcached的区别详解
  • Redis和Memcached的区别详解
  • Redis和Memcached的区别详解
  • Redis和Memcached的区别详解
Request.ServerVariables 大全

Request.ServerVariables("Url")返回服务器地址Request.ServerVariables("Path_Info")客户端提供的路...

python操作Kafka

目录一、python操作kafka1.python使用kafka生产者2.python使用kafka消费者3.使用docker中的kafka二、python操作kafka细...

Runtime.getRuntime().exec详解

Runtime.getRuntime().exec详解概述Runtime.getRuntime().exec用于调用外部可执行程序或系统命令,并重定向外部程序的标准输入、标准输出和标准错误到缓冲池。...

promise.all详解 promise.all是干什么的
promise.all详解 promise.all是干什么的

promise.all详解promise.all中所有的请求成功了,走.then(),在.then()中能得到一个数组,数组中是每个请求resolve抛出的结果...

2024-10-24 16:21 citgpt

Content-Length和Transfer-Encoding详解
  • Content-Length和Transfer-Encoding详解
  • Content-Length和Transfer-Encoding详解
  • Content-Length和Transfer-Encoding详解
  • Content-Length和Transfer-Encoding详解

取消回复欢迎 发表评论: