2023.10.14 关于 synchronized 基本介绍

news2024/12/29 8:56:38

目录

synchronized 的特性

互斥

理解阻塞等待

可重入

synchronized 的使用

修饰方法

修饰代码块


synchronized 的特性

  • JVM 称 synchronized 为监视器锁(monitor lock)

互斥

  •  synchronized 会起到互斥效果
  • 某个线程执行到某个对象的  synchronized 中时,其他线程如果也执行到同一个对象 synchronized 就会阻塞等待

理解阻塞等待

  • 针对每一把锁,操作系统内部都维护了一个等待队列
  • 当这个锁被某个线程占有的时候,其他线程尝试进行加锁,便加锁失败,从而阻塞等待
  • 一直等到线程解锁之后,有操作系统唤醒一个新的线程,再来获取这个锁

注意:

  • 线程A 解锁之后,先来的 线程B 并不会立即就能获取到锁,而是要通过操作系统来唤醒,属于操作系统线程调度的一部分工作
  • 通俗来说就是当 线程A 释放锁后,先来的 线程B 和后来的 线程C、线程D、线程E 会重新一起竞争锁,并不遵守先来后到的规则

可重入

  • 重入指一个线程针对同一个对象连续加锁两次
  • 如果没有问题则叫做 可重入
  • 如果有问题则叫做 不可重入,通常伴随出现死锁

  • 锁对象是 this 
  • 只要有线程调用 add 方法,进入 add 方法的时候,就会先尝试加锁
  • 如果此时成功加锁,紧接着遇到了代码块,再次尝试加锁
  • 站在 this (锁对象)的视角,它认为自己已经被另外的线程给占用了,这里的第二次加锁是否要阻塞等待
  • 当然此处是特殊情况,第二个线程和第一个线程为同一个线程
  • 从而此处如果允许再次加锁,该锁为可重入锁
  • 如果不允许再次加锁,而是发生阻塞等待,此时该锁为不可重入锁
  • synchronized 为可重入锁

例题引入

class Counter {
    public int count = 0;
    
    public void add() {
        count++;
    }
}
 
public class ThreadDemo13 {
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
//        搞两个线程,这两个线程分别针对 counter 来调用 5w 次的 add 方法
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 50000; i++) {
                counter.add();
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 50000; i++) {
                counter.add();
            }
        });
//        启动线程
        t1.start();
        t2.start();
//        等待两个线程结束
        t1.join();
        t2.join();
//        打印最终的 count 值
        System.out.println("count = " + counter.count);
    }
}

建议点击下方链接详细了解该例题后继续阅读下方内容

关于线程安全问题


synchronized 的使用

  • 明确 synchronized 是针对哪个对象加锁
  • 如果两个线程针对同一个对象进行加锁,就会出现锁竞争、锁冲突,一个线程能够获取到锁(先到先得)另一个线程阻塞等待,等待到上一个线程解锁,它才能获取锁成功
  • 如果两个对象针对不同对象加锁,此时不会发生锁竞争、锁冲突,这两线程都能获取到各自的锁,不会有阻塞等待

修饰方法

  • 普通方法:把锁加到 this 对象上

  • 静态方法:把锁加到类对象上
class MyClass {
    private static int count = 0;
    
    public static synchronized void increment() {
        count++;
    }
    
    public static int getCount() {
        return count;
    }
}
  • 静态方法只能被类本身调用
  • 当一个线程调用 increment 静态方法时,该线程将会对 MyClass 类加锁
  • 确保在执行 count++ 操作时不会有其他线程干扰
  • 该锁是基于类而不是实例

修饰代码块

  • 手动指定加到哪个对象上

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

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

相关文章

解决:PowerDesigne找不到右边表的工具栏

下载压缩包&#xff1a; PowerDesigner16.5压缩包 https://pan.baidu.com/s/1PxGafZUb5kcqSuPnxT4zgA?pwd6nyz http://PowerDesigner16.5压缩包 提取码&#xff1a;6nyz PowerDesigne破解版 找不到右边表的工具栏&#xff1f; 问题&#xff1a;PowerDesigner 快捷工具栏…

【C语言】通讯录的简单实现

通讯录的内容 contect.h #pragma once // 包含头文件 #include <stdio.h> #include <string.h> #include <assert.h> #include <stdlib.h>// 使用枚举常量定义功能 enum Function {quit, // 注意这是逗号&#xff0c;不是分号save,addition,delete,s…

TCP 协议的相关(部分)特性

TCP的报文结构 首部长度&#xff1a; 与UDP不同&#xff0c;TCP没有有描述数据的长度的变量&#xff08;UDP的是UDP长度&#xff09;&#xff0c;但有描述TCP的报头的长度&#xff0c;为什么要和UDP不同呢&#xff1f;其实是UDP的报头长度是固定的&#xff0c;而TCP的报头是“变…

2023-2024-1 for循环-1

7-1 求N分之一序列前N项和 本题要求编写程序&#xff0c;计算序列 1 1/2 1/3 ... 的前N项之和。 输入格式: 输入在一行中给出一个正整数N。 输出格式: 在一行中按照“sum S”的格式输出部分和的值S&#xff0c;精确到小数点后6位。题目保证计算结果不超过双精度范围。…

Golang中gRPC使用及原理探究

文章目录 概述gRPC的优势&#xff1a; 1、gRPC入门1.1 protobuf安装1.2 使用gRPC1.2.1 定义proto文件1.2.2 编译proto文件1.2.3 编写客户端和服务端代码 2、gRPC的通信模式2.1 一元RPC模式2.2 客户端流RPC模式2.3 服务端流RPC模式2.4双向流RPC模式 3、 gRPC的底层原理探究3.1 H…

基于php 进行每半小时钉钉预警

前言 业务场景&#xff1a;监控当前业务当出现并发情况时技术人员可以可以及时处理 使用技术栈&#xff1a; laravelredis 半小时触发一次报警信息实现思路 1、xshell脚本 具体参数就不详细解释了&#xff0c;想要详细了解可以自行百度 curl -H "Content-Type:appl…

10.数学环境排列数学公式

1.\begin{gathered} \begin{gathered} 是 LaTeX 中的数学环境&#xff0c;通常用于排列多行数学公式或方程组&#xff0c;这些公式或方程组需要在某种程度上垂直居中对齐。这个环境通常用于多行公式&#xff0c;与 align 或 eqnarray 不同&#xff0c;它不会自动对齐等号&…

OAuth2.0、和jwt、spring security之间的区别和联系

OAuth2.0的概念 OAuth 2.0开放授权&#xff0c;OAuth 2.0 是一种授权框架&#xff0c;用于授权第三方应用程序访问用户资源&#xff0c;而无需共享用户的凭据。它为用户提供了更好的隐私和安全性&#xff0c;并允许用户对授权进行细粒度的控制&#xff0c;颁发的token是第三方应…

Vue-2.9单页应用程序

单页应用程序&#xff08;SPA-Single Page Application&#xff09; 所有功能在一个html页面上实现 具体示例&#xff1a;网易云音乐https://music.163.com 京东淘宝等是多页面应用 单页VS多页 单页面应用&#xff1a;系统类网站、内部网站、文档类网站、移动端站点 多页面…

蓝桥杯 枚举算法 (c++)

枚举就是根据提出的问题&#xff0c;——列出该问题的所有可能的解&#xff0c;并在逐一列出的过程中&#xff0c;检验每个可能解是否是问题的真正解&#xff0c; 如果是就采纳这个解&#xff0c;如果不是就继续判断下一个。 枚举法一般比较直观&#xff0c;容易理解&#xff0…

python+django医患档案电子病历管理系统7ld2o

本课题使用Python语言进行开发。代码层面的操作主要在PyCharm中进行&#xff0c;将系统所使用到的表以及数据存储到MySQL数据库中&#xff0c;方便对数据进行操作本课题基于WEB的开发平台 1.运行环境&#xff1a;python3.7/python3.8。 2.IDE环境&#xff1a;pycharmmysql5.7; …

从Docker初识K8S

什么是Docker&#xff1f; 假设现在有一个服务场景&#xff0c;你是一个程序猿&#xff0c;你编写代码实现一个机器人喝水的功能&#xff0c;然后你需要将这份代码部署到每个机器人身上&#xff0c;你部署的时候需要一个个安装代码所需的依赖包&#xff0c;然后运行测试你的代码…

面向C++模块的开源 IFC SDK

早在 VS2019 v16.10 版本的时候&#xff0c;我们就官宣了对 C 模块(以及几乎所有其他 C 20 特性)的全面支持&#xff0c;包括 MSVC 编译器工具集&#xff0c;静态分析&#xff0c;智能感知和调试器等&#xff0c;而实现模块需要将 C 代码实现为一种内部的临时表示形式。 今天&…

【苍穹外卖 | 项目日记】第四天

前言&#xff1a; 今天状态还可以&#xff0c;既有自己实战独立写接口&#xff0c;又听了课&#xff0c;学习了新的知识 目录 前言&#xff1a; 今日完结任务&#xff1a; 今日收获&#xff1a; 实现店铺状态接口 杂项知识点&#xff1a; 总结&#xff1a; 今日完结任务…

华为9.20笔试 复现

第一题 丢失报文的位置 思路&#xff1a;从数组最小索引开始遍历 #include <iostream> #include <vector> using namespace std; // 求最小索引值 int getMinIdx(vector<int> &arr) {int minidx 0;for (int i 0; i < arr.size(); i){if (arr[i] …

重新认识面向对象

一、重新认识面向对象 1、重新认识面向对象1.1、理解隔离的变化1.2、各司其职1.3、对象是什么 2、面向对象设计基本原则&#xff08;八个原则&#xff09;先介绍分而治之的思想构造类介绍抽象类的方法构造类2.1、依赖倒置原则(DIP )2.2、开放封闭原则(OCP )2.3、单一职责原则&a…

推荐《咒术回战》

电视动画片《咒术回战》改编自芥见下下著作的同名漫画作品&#xff0c;于2019年11月25日宣布电视动画化的消息 [1] &#xff0c;该系列由MAPPA负责制作。第1期于2020年10月3日—2021年3月27日播出 [8] &#xff0c;全24集。 动画电影《咒术回战 0》于2021年3月27日宣布制作决…

实施 DevSecOps 最佳实践

DevSecOps 是一个框架&#xff0c;它将开发 (Dev)、IT 运营 (Ops) 和安全 (Sec) 流程的实践融合到一个简化的流程中。使用这种方法&#xff0c;DevSecOps 团队能够确保将安全性集成到软件开发生命周期中&#xff0c;确保以“安全第一”的心态构建、部署和维护软件。在本教程中&…

自动驾驶学习笔记(四)——变道绕行仿真

#Apollo开发者# 学习课程的传送门如下&#xff0c;当您也准备学习自动驾驶时&#xff0c;可以和我一同前往&#xff1a; 《自动驾驶新人之旅》免费课程—> 传送门 《2023星火培训【感知专项营】》免费课程—>传送门 文章目录 前言 仿真内容 启动Dreamview 开启Sim…

网络安全(黑客技术)——如何高效自学

前言 前几天发布了一篇 网络安全&#xff08;黑客&#xff09;自学 没想到收到了许多人的私信想要学习网安黑客技术&#xff01;却不知道从哪里开始学起&#xff01;怎么学&#xff1f;如何学&#xff1f; 今天给大家分享一下&#xff0c;很多人上来就说想学习黑客&#xff0c…