当前位置: 首页 > wzjs >正文

做网站的那家公司好武汉关键词排名工具

做网站的那家公司好,武汉关键词排名工具,12306网站建设 实际,php做网站的分站目录 一、线程同步与线程安全问题线程不安全Demo线程不安全的原因 二、synchronized关键字关键字锁粒度修饰对象修饰代码块修饰方法修饰静态方法修饰类 synchronized 锁总结 synchronized加锁原理MarkWordsynchronized锁升级synchronized锁原理synchronized关键字总结 其他同步…

目录

    • 一、线程同步与线程安全问题
      • 线程不安全Demo
      • 线程不安全的原因
    • 二、synchronized关键字
      • 关键字锁粒度
        • 修饰对象
        • 修饰代码块
        • 修饰方法
        • 修饰静态方法
        • 修饰类
      • synchronized 锁总结
    • synchronized加锁原理
      • MarkWord
      • synchronized锁升级
      • synchronized锁原理
      • synchronized关键字总结
    • 其他同步方式
      • 乐观锁
      • Lock类的加锁、解锁
      • 分布式锁(redis)

一、线程同步与线程安全问题

线程不安全Demo

我们下面就看一个出现线程不安全情况的示例

class UnsafeThreadDemo {private int count;public MultiUnSafeDemo(int count) {this.count = count;}public void getAndIncrement() {count++;}public static void main(String[] args) throws InterruptedException {final MultiUnSafeDemo counter = new MultiUnSafeDemo(0);Thread []threads = new Thread[100];for(int i=0; i<threads.length; i++) {threads[i] = new Thread(() -> {for(int j=0; j<1000; j++) {counter.getAndIncrement();}});threads[i].start();}for(int i=0; i<threads.length; i++) {threads[i].join();}System.out.println("count: "+counter.count);}
}

运行结果,结果显示count并非100000,那又是为什么呢?
在这里插入图片描述

线程不安全的原因

问题出现在count++ 并非原子操作,i++分为三个步骤

  • 读取当前值
  • 当前值+1
  • 写回内存

线程之间的切换,可能发生在任意过程,e.g. 线程a已经加完1,但是发生线程切换,当前值被原由的线程b的值覆盖,导致实际执行100个线程的总和并非100*1000,发生线程切换的位置可能导致实际值比理论值小。

二、synchronized关键字

java中提供了一些解决线程安全问题的工具,有Lock类,有synchronized关键字,这里先介绍synchronized关键字

关键字锁粒度

修饰对象

synchronized 可以修饰对象,例如通过new ClassName() 创建的 对象,例如在代码的共享变量区域使用synchronized(this) ,可以保障线程安全,如果在第一部分的示例中使用synchronized(this) 覆盖 count++的代码块,可以保障最终的结果正确输出100000:

public class MultiUnSafeDemo {private int count;public MultiUnSafeDemo(int count) {this.count = count;}public void getAndIncrement() {synchronized (this) {count++;}}public static void main(String[] args) throws InterruptedException {final MultiUnSafeDemo counter = new MultiUnSafeDemo(0);Thread []threads = new Thread[100];for(int i=0; i<threads.length; i++) {threads[i] = new Thread(() -> {for(int j=0; j<1000; j++) {counter.getAndIncrement();}});threads[i].start();}for(int i=0; i<threads.length; i++) {threads[i].join();}System.out.println("count: "+counter.count);}
}

在这里插入图片描述
此时,由于代码的getAndIncrement方法被对象调用,因此synchronized (this) 等价于对象锁,锁的是调用这个方法的对象。通过this对象调用方法的synchornized,实现非原子性的**count++**操作的同步。

修饰代码块

除了修饰对象,可以将synchronized关键字修饰代码中共享变量的区域,保证操作共享变量的一致性。

public class Cache {private final Object lock = new Object();private Map<String, String> data = new HashMap<>();public void put(String key, String value) {synchronized (lock) { // 锁定私有对象,避免暴露锁data.put(key, value);}}
}

上述示例中,synchronized关键字修饰lock这个类的变量,实现操作data这个hashMap的线程同步性

修饰方法

可以将synchornized关键字添加到方法前,调用方法的时候会实现多线程的同步

  public synchronized void getAndIncrement() {count++;}

效果和在方法内部增加synchronized () {} 代码块相同,都是锁定这个实例

优点:实现简单,方便
缺点:可能将方法中不需要同步的部分也控制住,降低了程序的并发性。

修饰静态方法

等价于修饰类,因为静态方法的生命周期和类相同,因此在静态方法上加锁,锁定的是类所有实例,在一台机器上的对象实例都串行执行


修饰类

通过synchronized (XXXName.Class) 实现锁对象

public class DatabaseConnection {public void init() {// 同步代码块,锁定类的 Class 对象synchronized (DatabaseConnection.class) {// 初始化数据库连接(全局唯一操作)}}
}

锁的类型为 类对象,适用场景为全局:

  • 全局锁

synchronized 锁总结

Synchronized基于类、对象、方法、静态方法的使用修饰,有以下几种形式,整理为:

锁类型锁对象同步范围适用场景
对象锁对象实例,以及对象调用方法当前实例的线程非静态的示例方法
类锁Class对象所有实例的对象静态变量保护或全局操作,例如数据库连接池的初始化
同步代码块显示指定的对象代码块包含的区域同步耗时操作中的关键部分

synchronized加锁原理

MarkWord

每个 Java 对象在内存中由 对象头(Header)、实例数据(Instance Data) 和 对齐填充(Padding) 组成。synchronized 的锁信息存储在对象头中,具体分为两部分:

Mark Word:记录对象的哈希码、GC 分代年龄、锁状态标志等。

Klass Pointer:指向对象所属类的元数据。

锁状态标志 通过 Mark Word 的特定比特位表示,支持以下状态:

  • 无锁(001)
  • 偏向锁(101)
  • 轻量级锁(00)
  • 重量级锁(10)

synchronized锁升级

为了提高性能,JVM 会根据线程竞争情况动态调整锁的级别,从低开销到高开销逐步升级:

(1) 偏向锁(Biased Locking)
**适用场景:**单线程访问同步代码块。

原理:
对象头记录第一个获取锁的线程 ID(Thread ID),后续该线程无需通过 CAS 加锁和解锁。

(2) 轻量级锁(Lightweight Locking)

适用场景:
多线程交替执行,无实际竞争。

原理:

线程通过 CAS 操作 将对象头的 Mark Word 替换为指向线程栈中锁记录(Lock Record)的指针。

若成功,线程获得轻量级锁;若失败(有其他线程竞争),升级为重量级锁。

(3) 重量级锁(Heavyweight Locking)

适用场景:
多线程高竞争。

原理:

通过操作系统的 互斥量(Mutex) 实现,未获取锁的线程会被阻塞,进入内核态等待唤醒。

代价:涉及用户态到内核态的切换,性能开销较大。

synchronized锁原理

synchronized关键字修饰方法或者代码块的时候,增加了synchronized修饰的代码块在反编译为字节码的时候,都增加了monitorenter和monitorexit,monitorenter进入临界区,申请锁定资源。执行完同步代码后,monitorexit退出临界区。

synchornized修饰方法的时候,使用ACC_SYNCHRONIZED标记被修饰的方法

每个 Java 对象关联一个 监视器锁(Monitor),其本质是一个 互斥锁(Mutex)。Monitor 的实现依赖操作系统,核心操作包括:

  • 进入区(Entry Set):线程尝试获取锁,若失败则进入阻塞队列。

  • 拥有者(Owner):持有锁的线程。

  • 等待区(Wait Set):调用 wait() 的线程释放锁并进入等待状态。

synchronized关键字总结

对象头与锁状态:通过 Mark Word 记录锁状态,支持偏向锁、轻量级锁、重量级锁的升级。

锁升级机制:根据线程竞争动态调整锁级别,平衡性能与安全性。

字节码实现:依赖 monitorenter 和 monitorexit 指令,同步方法使用 ACC_SYNCHRONIZED 标记。

JVM 优化:锁消除和锁粗化减少不必要的同步开销。

适用场景:偏向锁和轻量级锁适用于低竞争场景,重量级锁应对高并发竞争。

其他同步方式

乐观锁

通过版本号,根据写入的时候的版本号和当前期望是否一致判断是否可以执行写入操作,是一种无锁的同步

Lock类的加锁、解锁

Lock的lock方法适用于单实例,单JVM的同步锁,支持可重入锁、自旋锁、中断锁

分布式锁(redis)

使用redis的单线程,根据Lua脚本和setnx保障分布式环境中的全局原子性以及超时设置

http://www.dtcms.com/wzjs/351964.html

相关文章:

  • 网站里的专题页面百度怎么创建自己的网站
  • 周口建设网站平台推广
  • 大尺寸图网站网络营销的概念和含义
  • 做网站图标的软件站长之家官网登录入口
  • 成都网站建设名录广告媒体资源平台
  • 贝壳企业网站管理系统明星百度指数在线查询
  • 青岛 机械 中企动力提供网站建设百度收录查询
  • 碗网站宁波网络营销公司
  • 世界做诡异的地方网站技能培训班有哪些
  • 使用java做后台网站seo优化技术排名
  • 成都个人兼职做网站百度竞价渠道代理商
  • 网站评论 设计万能导航网
  • 在家做兼职的正规网站平台广东河源最新疫情
  • 广东哪家网站建设上海最新新闻热点事件
  • 自动网站建设企业的互联网推广
  • 网站开发的关键技术与难点推广赚钱的平台
  • 如何做网站自适应营销网站建设哪家好
  • 近期莱芜命案有名的seo外包公司
  • 网站做搜索关键字好吗seo海外推广
  • wood怎么做网站结构图百度seo白皮书
  • 网站空间怎么续费站长工具免费
  • 行政事业单位网站建设东莞百度快速排名优化
  • 无锡网站排名提升百度广告优化师
  • 合肥疫情风险等级最新网站专业术语中seo意思是
  • 网站建设 上海seo顾问是什么
  • 温州建设小学的网站徐州seo培训
  • 上饶市建设局有什么网站营销成功的案例
  • 建设网站考虑因素seo博客是什么意思
  • 高大上的公司网站网络营销师
  • 网站后台模板安装显示不了交换链接的其它叫法是