【JavaEE】_synchronized关键字——监视器锁monitor lock

目录

1. synchronized的特性

2. synchronized的使用

3. Java标准库中的线程安全类


1. synchronized的特性

(1)互斥:

前文已经介绍,某个线程执行到某个对象的synchronized中时,其他线程如果也执行到同一个对象,synchronized就会阻塞等待,进入synchronized修饰的代码块相当于加锁,退出synchronized修饰的代码块相当于解锁;

(2)刷新内存:

前文介绍内存可见性时已经提到:synchronized的工作过程是:

① 获得互斥锁,② 从内存拷贝变量的最新内存到寄存器,③ 执行代码,

④ 将更改后的共享变量的值刷新到寄存器,⑤ 释放互斥锁;

故而synchronized也可以保证内存的可见性;

(3)可重入:

同一个线程针对同一个锁连续加两次,如果出现了死锁就是不可重入,不会死锁就是可重入;

(3.1)死锁:

class Counter{public int count=0;synchronized public void increase(){synchronized (this){count++;}}
}

外层先加了一次锁,内层又对同一对象再次加锁,此时由于外层锁需要执行完内部代码才能解锁,而内层锁需要等待已经先锁的外层锁解锁后才能执行,此时就会形成死锁;

(3.2)可重入锁:

为了解决这个问题,JVM内部将synchronized实现为可重入锁。

可重入锁会记录当前占用锁的线程以及加锁次数,线程a第一次加锁成功后,锁内部就会记录当前占用锁的线程为a,同时加锁次数为1,后续线程a再加锁时,进行的加锁操作就非真实的加锁操作而是一个伪加锁,是没有实质影响的,只是将加锁次数增加为2;

代码执行完毕解锁时,会将计数-1,当锁的计数减到0时,才会真的解锁;

可重入锁降低了程序员的编写负担,降低了使用成本,提高了开发效率,但同时由于需要维护锁所属的线程以及加减计数会降低运行效率,程序的开销也会更大;

(3.3)死锁的必要条件:

① 互斥使用:一个锁被一个线程占用后,其他线程就无法占用;

② 不可抢占:一个锁被一个线程占用后,其他线程不能抢占该锁;

③ 请求与保持:当一个线程占据了多把锁之后除非显式释放锁,否则这些锁始终被该线程持有;

(以上三条都是锁本身的特点)

④ 环路等待:等待关系成环;

在实际开发中需要避免死锁,关键还是从避免环路等待入手:

针对多把锁加锁时约定好固定的顺序,就可以避免等待关系成环;

但实际情况中很少出现一个线程套锁的问题;

2. synchronized的使用

使用synchronized的本质是修改了Object对象中“对象头”内的一个标记;

(1)直接修饰普通方法:此时锁对象是this:

class Counter{public int count=0;synchronized public void increase(){count++;}
}

 当两个线程同时对同一个对象进行加锁的时候才存在竞争;

(2)修饰一个代码块:需要显式指定锁对象:

class Counter{public int count=0;public void increase(){synchronized (this){count++;}}}
public class Demo1 {private static Counter counter = new Counter();public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(()->{for(int i=0;i<50000;i++){counter.increase();}});Thread t2 = new Thread(()->{for(int i=0;i<50000;i++){counter.increase();}});t1.start();t2.start();t1.join();t2.join();System.out.println(counter.count);}
}

counter.increase()表示针对this对象进行加锁操作;

注:任何对象都可以进行加锁是java语言的特色;

(3)修饰一个静态方法:

静态方法其实就是类方法,普通方法就是实例方法;故而

synchronized修饰一个静态方法就相当于针对当前类的类对象加锁

class Counter{synchronized public static void func1(){}public static void fun2(){synchronized (Counter.class){}}
}

如在上文代码中,静态方法func1是表示为synchronized修饰的静态方法,其效果等效于静态方法func2;

注:(1)类对象就是运行程序时.class文件被加载到JVM内存中时的形态;

(2)使用synchronized很容易造成线程阻塞,一旦线程阻塞,此时放弃CPU,再次回到CPU的时间就不可控了,一旦代码中使用了synchronized,则“高性能”几乎无法实现;

3. Java标准库中的线程安全类

Java标准库中已经实现的类中有些是线程安全的,有些是线程不安全的:

线程不安全类:

①ArrayList ②LinkedList ③HashMap ④TreeMap ⑤HashSet ⑥TreeSet ⑦StringBuilder

线程安全类:

①Vector(不推荐) ②HashTable(不推荐)③ConcurrentHashMap ④StringBuffer ⑤String

注:(1)线程安全类由于一些关键方法都被synchronized修饰,保证了多线程环境下修改同一个对象不会出现线程不安全问题;

(2)String是线程安全类不是因为synchronized修饰,而是因为String是不可变对象,不存在多线程中修改造成的线程不安全问题;

同时请注意不可变对象与常量以及final没有必然联系:

不可变对象是指在该类中没有提供public的修改属性的方法,final修饰类表示类不可继承;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2808165.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Git笔记——4

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 一、操作标签 二、推送标签 三、多人协作一 完成准备工作 协作开发 将内容合并进master 四、多人协作二 协作开发 将内容合并进master 五、解决 git branch -a…

第十二章 Linux——日志管理

第十二章 Linux——日志管理 基本介绍系统常用日志日志管理服务日志轮替基本介绍日志轮替文件命名logrotate配置文件自定义加入日志轮转应用实例 日志轮替机制原理查看内存日志 基本介绍 日志文件是重要的系统信息文件&#xff0c;其中记录了许多重要的系统事件&#xff0c;包…

【操作系统】磁盘文件管理系统

实验六 磁盘文件管理的模拟实现 实验目的 文件系统是操作系统中用来存储和管理信息的机构&#xff0c;具有按名存取的功能&#xff0c;不仅能方便用户对信息的使用&#xff0c;也有效提高了信息的安全性。本实验模拟文件系统的目录结构&#xff0c;并在此基础上实现文件的各种…

[c++] 工厂模式 + cyberrt 组件加载器分析

使用对象的时候&#xff0c;可以直接 new 一个&#xff0c;为什么还需要工厂模式 &#xff1f; 工厂模式属于创建型设计模式&#xff0c;将对象的创建和使用进行解耦&#xff0c;对用户隐藏了创建逻辑。 个人感觉上边的表述并没有说清楚为什么需要使用工厂模式。因为使用 new 创…

12个的无时间限制的录屏软件详细比较

您可能尝试过许多录制程序&#xff0c;但大多数都会在30 分钟后停止录制萤幕。如果您需要录制较长的内容&#xff0c;特别是为公司会议或简报进行录制&#xff0c;您将必须找到最好的没有时间限制的录屏软件。这款录音软体可以让您长时间录音而没有任何麻烦。下面列出了12 款无…

亚马逊产品数据抓取

抓取数据 启动抓取 &#xff0c;亚马逊平台前台网站中可以查看、抓取、分析的一系列数据源&#xff0c;其数据种类繁多&#xff0c;本系统主要抓取产品列表&#xff08;包含主图、标题、价格、review分值、prime服务信息等&#xff09;、Listing详情信息&#xff08;包含5点描…

MyBatis---初阶

一、MyBatis作用 是一种更简单的操作和读取数据库的工具。 二、MyBatis准备工作 1、引入依赖 2、配置Mybatis(数据库连接信息) 3、定义接口 Mapper注解是MyBatis中用来标识接口为Mapper接口的注解。在MyBatis中&#xff0c;Mapper接口是用来定义SQL映射的接口&#xff0c;通…

超68万售出,sedo域名登顶最新一期交易排行榜

.com三字母域名售价超过68万人民币&#xff0c;币圈对应的四字母域名近期被曝光售价超过68万人民币。 近日&#xff0c;sedo平台交易信息显示&#xff0c;一个三字母域名被拍卖出10.5万美元&#xff0c;折合人民币超过68万人民币。 据查询&#xff0c;其注册时间为1995年&…

【FreeRTOS】任务创建

参考博客&#xff1a; ESP-IDF FreeRTOS 任务创建分析 - [Genius] - 博客园 (cnblogs.com) 1.什么是任务 1&#xff09;独立的无法返回的函数称为任务 2&#xff09;任务是无线循环 3&#xff09;无返回数据 2.任务的实现过程 1.定义任务栈 裸机程序&#xff1a;统一分配到一…

五种多目标优化算法(MOFA、NSWOA、MOJS、MOAHA、MOPSO)性能对比(提供MATLAB代码)

一、5种多目标优化算法简介 多目标优化算法是用于解决具有多个目标函数的优化问题的一类算法。其求解流程通常包括以下几个步骤&#xff1a; 1. 定义问题&#xff1a;首先需要明确问题的目标函数和约束条件。多目标优化问题通常涉及多个目标函数&#xff0c;这些目标函数可能…

软考44-上午题-【数据库】-数据定义语言DDL

一、SQL server数据库的体系结构 SQL server数据库的体系结构是由视图、基本表、存储文件&#xff0c;三级结构组成。 【回顾】&#xff1a;数据库的三级模式结构 视图&#xff1a;外模式 存储文件&#xff1a;内模式 基本表&#xff1a;概念模式 二、SQL语言的分类 SQL语言按…

Yolo v9 “Silence”模块结构及作用!

论文链接&#xff1a;&#x1f47f; YOLOv9: Learning What You Want to Learn Using Programmable Gradient Information 代码链接&#xff1a;&#x1f47f; https://github.com/WongKinYiu/yolov9/tree/main Silence代码 class Silence(nn.Module):def __init__(self):supe…

2024最新零基础入门|白帽黑客学习教程,从0到黑客高手!

新手如何通过自学黑客技术成为厉害的白帽黑客&#xff1f; 我目前虽然算不上顶尖的白帽大佬&#xff0c;但自己在补天挖漏洞也能搞个1万多块钱。 给大家分享一下我的学习方法&#xff0c;0基础也能上手学习,如果你能坚持学完&#xff0c;你也能成为厉害的白帽子&#xff01; …

Escalate_Linux(4)-利用SUDO实现提权

利用SUDO实现提权 利用用户的sudo授权获得root的shell cat /etc/passwd cat /etc/sudoers 命令没有权限 echo "cat /etc/sudoers" >/tmp/ls chmod 755 /tmp/ls export PATH/tmp:$PATH /home/user5/script 想办法更改user1的口令 echo echo "user1:xiao…

【电子通识】为什么单片机芯片上会有多组VDD电源?

在单片机芯片规格书中&#xff0c;我们经常能看到多个组VDD的设计&#xff0c;如下红框所示管脚都是VDD管脚。 为什么需要这样设计&#xff1f;只设置一个VDD管脚&#xff0c;把其他的VDD管脚让出来多做几个IO或是其他复用功能不好吗&#xff1f;接下来我们从单片机内部的电路结…

ubuntu 22.04LTS的一些使用心得

前言 笔者一直在折腾ubuntu作为开发的主力系统&#xff0c;尤其是最近微信和各种软件陆续支持Debian系列&#xff0c;很多软件都可以用了&#xff0c;当然开源的软件大部分是跨平台的&#xff0c;尤其是idea系列。 X11 OR Wayland 关于X11和wayland&#xff0c;笔者还是使用…

CSRF靶场实战

DVWA靶场链接&#xff1a;https://pan.baidu.com/s/1eUlPyB-gjiZwI0wsNW_Vkw?pwd0b52 提取码&#xff1a;0b52 DVWA Low 级别打开靶场&#xff0c;修改密码 复制上面的 url&#xff0c;写个简单的 html 文件 <html <body> <a hrefhttp://127.0.0.1/DVWA/vulne…

leetcode hot100 买卖股票最佳时机3

本题中&#xff0c;依旧可以采用动态规划来进行解决&#xff0c;之前的两个题我们都是用二维数组dp[i][2]来表示的&#xff0c;其中i表示第i天&#xff0c;2表示长度为2&#xff0c;其中0表示不持有&#xff0c;1表示持有。 本题中&#xff0c;说至多完成两笔交易&#xff0c;也…

Linux系统添加新的网卡,并启用

在Rocky Linux系统中添加新的网卡并启用&#xff0c;一般涉及到以下步骤&#xff1a; 物理连接网卡&#xff1a; 首先确保你的虚拟机已经正确连接了新的网络适配器。 查看新添加的网卡&#xff1a; 在终端中输入以下命令来列出所有已识别的网络接口&#xff1a; ip link show …

基础复习(GDB调试)

1.GDB环境配置 这里只说Pwndbg Pwndbg的安装简单&#xff0c;访问Github主页&#xff0c;https://github.com/pwndbg/pwndbg 在“How”栏中看到安装说明 2.打开文件 GDB打开文件的方式与图形化的工具不同&#xff0c;需要通过传入参数或执行命令 方式1&#xff1a;在GDB的…