17 synchronized关键字使用 synchronized方法、synchronized块

synchronized方法、synchronized块

    • 线程的同步
    • 不安全的线程
      • 示例1:
      • 示例2
      • 示例3
    • synchronized方法、synchronized块

线程的同步

并发:同一个对象被多个线程同时操作。

解决方案:让多个线程排队操作对象。

使用队列和锁解决多线程的并发问题。

同进程的多线程共享同一块存储空间,当多个线程同时访问某块内存空间时,就存在并发问题。为了保证数据在方法中被访问时的正确性,在访问时加入锁机制synchronized;当线程获得对象的排它锁,该线程独占资源,其他线程必须等待其使用后释放锁即可。

同时也伴随着一些问题:

  • 一个线程持有锁导致其它线程所有需要此锁的线程挂起
  • 在多线程竞争下,加锁,释放锁会导致比较多的上下文切换和调度延时,导致性能问题
  • 也可能存在优先级高的线程等待优先级低的线程释放锁,而导致性能问题。

不安全的线程

通过下面例子说明,线程是不安全。

重复执行下面方法,执行结果可能会有多种情况。

示例1:

//每次执行结果都不是我们预想的结果
public class UnsafeBuyTicket {public static void main(String[] args) {BuyTicket buyTicket = new BuyTicket();new Thread(buyTicket,"张三").start();new Thread(buyTicket,"李四").start();new Thread(buyTicket,"王五").start();}
}class BuyTicket implements Runnable {private int ticketNums = 10;boolean flag = true;@Overridepublic void run() {while (flag) {buy();}}//synchronized 同步方法 锁的是this 即BuyTicket对象private /**synchronized*/ void buy() {if (ticketNums <= 0) {flag = false;return;}try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "买到票" + ticketNums--);}
}
张三买到票9
李四买到票8
王五买到票10
李四买到票7
王五买到票6
张三买到票7
张三买到票5
李四买到票4
王五买到票5
李四买到票3
张三买到票3
王五买到票3
王五买到票2
张三买到票2
李四买到票2
李四买到票1
王五买到票1
张三买到票1

示例2

public class UnsafeBank {public static void main(String[] args) {Account funds = new Account("家庭基金", 100);new TakeMoney(funds,60,"you").start();new TakeMoney(funds,80,"youWife").start();}}class Account{String name;int money;public Account(String name, int money) {this.name = name;this.money = money;}
}class TakeMoney extends Thread{Account account;int takeMoney;//取多钱钱int nowMoney;//你口袋里面的钱public TakeMoney(Account account, int takeMoney, String name) {super(name);this.account = account;this.takeMoney = takeMoney;}//synchronized run 是不行的@Overridepublic void run() {//synchronized (account) {if ((account.money - takeMoney) < 0) {System.out.println(Thread.currentThread().getName() + "余额不足。");return;}try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}account.money = account.money - takeMoney;nowMoney = nowMoney + takeMoney;System.out.println(account.name + "余额为:" + account.money);System.out.println(this.getName() + "口袋里面的钱:" + nowMoney);//}}
}
//执行结果
家庭基金余额为:-40
家庭基金余额为:-40
you口袋里面的钱:60
youWife口袋里面的钱:80

示例3

public class UnsafeList {public static void main(String[] args) throws InterruptedException {List<String> list = new ArrayList<String>();for (int i = 0; i < 10000; i++) {new Thread(() -> {//synchronized (list) {list.add(Thread.currentThread().getName());// }}).start();}Thread.sleep(3000);//确保上面线程能够执行完毕后在打印list.sizeSystem.out.println(list.size());}
}
//执行结果
9999

针对上面示例,添加synchronized关键字,使其变为线程安全的。

synchronized方法、synchronized块

关键字synchronized可以修饰方法或者以同步块的形式来进行使用,它主要确保多个线程在同一个时刻,只能有一个线程处于方法或者同步块中,它保证了线程对变量访问的可见性和排他性

synchronized方法控制对象的访问,每个对象对应一把锁,每个synchronized方法都必须获得该方法对象的锁才能执行,否则会阻塞线程,方法执行时独占该锁,知道方法执行完毕才会释放锁。

同步块:synchronized(object){}

synchronized修饰的代码块,会在object对象上加一个监视器。而同步方法会在当前对象this上增加一个监视器。

synchronized同步代码块一般加载共享资源对象上。

 //示例1 将buy方法改为同步方法private synchronized void buy()//示例2 试图按照示例1的方案 将run方法改为同步方法,验证是不行的,因为加上run方法的synchronized将对TakeMoney类添加的监视器,但最终操作的确是account对象,//此示例 多线程操作的共共享资源是account,并非TakeMoney//示例3 在共享资源list增加synchronized关键字,为其添加监视器

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Harbor.cfg 配置文件参数详解

目录 Harbor.cfg 配置文件参数详解 所需参数&#xff1a; hostname&#xff1a; ui_url_protocol&#xff1a; max_job_workers&#xff1a; db_password&#xff1a; customize_crt&#xff1a; ssl_cert&#xff1a; ssl_cert_key&#xff1a; secretkey_path&#…

力扣:56. 合并区间(Python3)

题目&#xff1a; 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 来源&#xff1a;力扣&#xff08;Lee…

DAY03_Spring—SpringAOPAOP切入点表达式AOP通知类型Spring事务管理

目录 一 AOP1 AOP简介问题导入1.1 AOP简介和作用1.2 AOP中的核心概念 2 AOP入门案例问题导入2.1 AOP入门案例思路分析2.2 AOP入门案例实现【第一步】导入aop相关坐标【第二步】定义dao接口与实现类【第三步】定义通知类&#xff0c;制作通知方法【第四步】定义切入点表达式、配…

(八)穿越多媒体奇境:探索Streamlit的图像、音频与视频魔法

文章目录 1 前言2 st.image&#xff1a;嵌入图像内容2.1 图像展示与描述2.2 调整图像尺寸2.3 使用本地文件或URL 3 st.audio&#xff1a;嵌入音频内容3.1 播放音频文件3.2 生成音频数据播放 4 st.video&#xff1a;嵌入视频内容4.1 播放视频文件4.2 嵌入在线视频 5 结语&#x…

MySQL面试1

Mysql的面试突击1 Mysql的体系结构是什么样子的&#xff08;查询语句怎么进行执行的&#xff09; mysql的架构&#xff1a;单进程多线程的架构模式 CLient -----> Server架构 Mysql的链接方式有没有性能优化的点 2个点 查询缓存(Query Cache) MySQL 内部自带了一个缓存模…

spring事务和数据库事务是怎么实现

Spring事务的原理 Spring事务的本质其实就是数据库对事务的支持&#xff0c;没有数据库的事务支持&#xff0c;spring是无法提供事务功能的。对于纯JDBC操作数据库&#xff0c;想要用到事务&#xff0c;可以按照以下步骤进行&#xff1a; 获取连接 Connection con DriverManag…

SpringBoot yml配置注入

yaml语法学习 1、配置文件 SpringBoot使用一个全局的配置文件 &#xff0c; 配置文件名称是固定的 application.properties 语法结构 &#xff1a;keyvalue application.yml 语法结构 &#xff1a;key&#xff1a;空格 value 配置文件的作用&#xff1a;修改SpringBoot自动…

Spring Boot集成EasyExcel实现excel导入导出操作

文章目录 Spring Boot集成EasyExcel实现excel导入导出操作0 简要说明简单使用读操作excel源文件实体类监听器业务代码 写操作*实体类*excel示例业务代码根据参数指定列导出指定哪几列导出复杂头导出 关于数值型&#xff0c;日期型&#xff0c;浮点型数据解决方案实体类接收字符…

算法通过村第二关-链表黄金笔记|K个一组反转

文章目录 前言链表反转|K个一组翻转链表解题方法&#xff1a;头插法处理&#xff1a;穿针引线法处理&#xff1a; 总结 前言 提示&#xff1a;没有人天生就喜欢一种气味而讨厌另一种气味。文明的暗示而已。 链表反转|K个一组翻转链表 给你链表的头节点 head &#xff0c;每 k…

【css】textarea-通过resize:none 禁止拖动设置大小

使用 resize 属性可防止调整 textareas 的大小&#xff08;禁用右下角的“抓取器”&#xff09;&#xff1a; 没有设置resize:none 代码&#xff1a; <!DOCTYPE html> <html> <head> <style> textarea {width: 100%;height: 150px;padding: 12px 20p…

源码分析——HashMap(JDK1.8)源码+底层数据结构分析

文章目录 HashMap 简介底层数据结构分析JDK1.8之前JDK1.8之后 HashMap源码分析构造方法put方法get方法resize方法 HashMap常用方法测试 HashMap 简介 HashMap 主要用来存放键值对&#xff0c;它基于哈希表的Map接口实现&#xff0c;是常用的Java集合之一。 JDK1.8 之前 HashM…

HBase-写流程

写流程顺序正如API编写顺序&#xff0c;首先创建HBase的重量级连接 &#xff08;1&#xff09;读取本地缓存中的Meta表信息&#xff1b;&#xff08;第一次启动客户端为空&#xff09; &#xff08;2&#xff09;向ZK发起读取Meta表所在位置的请求&#xff1b; &#xff08;…

python实现简单的爬虫功能

前言 Python是一种广泛应用于爬虫的高级编程语言&#xff0c;它提供了许多强大的库和框架&#xff0c;可以轻松地创建自己的爬虫程序。在本文中&#xff0c;我们将介绍如何使用Python实现简单的爬虫功能&#xff0c;并提供相关的代码实例。 如何实现简单的爬虫 1. 导入必要的…

1、如何实现两台电脑之间数据相互读写

一、确保两台电脑在同一个局域网中&#xff0c;可以使用网线【动态配置】进行两台电脑互连。 二、静态配置: 将IP地址和网关设为192.168.0.1&#xff0c;目的是让这台电脑做另一台电脑的网关&#xff0c;子网掩码一点击会自动添加。第二台电脑同样打开设置&#xff0c;此处IP地…

DT昆虫绑定学习(没蒙皮)

SelectEdgeLoopSp; ConvertSelectionToVertices;selectType -ocm -alc false; selectType -ocm -polymeshVertex true; CreateCluster; 连接到物体 global proc matchTrns() { string $mtr[] ls -sl; if (size($mtr) < 2){ warning "MUST select 2 objects!"…

SQL分类及通用语法数据类型(超详细版)

一、SQL分类 SQL是结构化查询语言&#xff08;Structured Query Language&#xff09;的缩写。它是一种用于管理和操作关系型数据库系统的标准化语言。SQL分类如下&#xff1a; DDL: 数据定义语言&#xff0c;用来定义数据库对象&#xff08;数据库、表、字段&#xff09;DML:…

Docker学习(二十四)报错速查手册

目录 一、This error may indicate that the docker daemon is not running 报错docker login 报错截图&#xff1a;原因分析&#xff1a;解决方案&#xff1a; 二、Get "https://harbor.xxx.cn/v2/": EOF 报错docker login 报错截图&#xff1a;原因分析&#xff1a…

【从零学习python 】08.Python了解位运算符, 运算符优先级

文章目录 位运算符&#xff08;了解&#xff09;练习 运算符优先级练习 总结&#xff1a;进阶案例 位运算符&#xff08;了解&#xff09; 按位运算符是把数字看作是二进制来进行计算的。 下表中变量 a 为 60&#xff0c;b 为 13&#xff0c;二进制格式如下&#xff1a; a 0…

重置 Macbook 中MySQL 的 root 用户密码

Mac上好久前安装测试用的MySQL的Root密码忘记&#xff0c;猜了些常用密码都不对&#xff0c;只能重置密码。 重置密码 1、关闭MySQL服务&#xff0c;可以直接在系统偏好里关闭 sudo /usr/local/mysql/support-files/mysql.server stop 2、进入安装目录&#xff0c;启动安全…

DARPA TC-engagement5数据集解析为json格式输出到本地

关于这个数据集的一些基本信息就不赘述了&#xff0c;参考我之前的博客。DARPA TC-engagement5数据集官方工具可视化 官方给的工具是将解析的数据存到elasticsearch的&#xff0c;但是数据集的解压增长率非常恐怖&#xff0c;对空间要求很高。因此针对这个问题&#xff0c;我对…