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

已有网站做百度推广郑州seo多少钱

已有网站做百度推广,郑州seo多少钱,做校园后勤管理网站得重点难点,做家教去哪个网站目录 一、线程同步与线程安全问题线程不安全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.cadmedia.cn/news/1563.html

相关文章:

  • 贵阳房地产网站建设网络推广的平台
  • 北京论坛建站模板山东疫情最新情况
  • 徐州城建吧惠州seo按天付费
  • 河北沧州网站建设信阳百度推广公司电话
  • 网站后台管理系统教程杭州网站优化流程
  • 网站建设织梦怎么样站长工具seo综合查询
  • 微信网站怎么写品牌营销和市场营销的区别
  • 我要做网站推广防止恶意点击软件管用吗
  • 浙江省住房和城乡建设厅网站 文件网站制作需要多少钱
  • 成都网站建设好多科技新媒体运营需要哪些技能
  • 如何免费网站建设厦门seo排名优化
  • 烟台教育网站建设企业培训师
  • 设计企业网站哪家好推广员是干什么的
  • html源码网站下载之家自己怎么优化网站排名
  • 宁波建网站需要什么怎么建立一个属于自己的网站
  • 惠州网站制作询问薇大连网站开发公司
  • 带空间二字的韩国视频网站找竞价托管公司
  • 贵州建设监理网站培训通知栏什么时候网络推广
  • 购物网站需求分析报告seo点击软件排名优化
  • 天津市建设监理协会网站潍坊百度网站排名
  • 2020年网站建设笔记本今日关键词
  • 浦东网站建设哪家好百度渠道开户哪里找
  • 菏泽市建设局网站电话号码产品推广方案范文500字
  • 水碓子网站建设深圳seo优化公司排名
  • 网站做订购网游推广
  • 江桥网站建设百度网址查询
  • 容易被百度收录的网站抖音权重查询工具
  • 中央农村工作会议2020原文网站优化 福州
  • 公众号开发用什么语言优化师是做什么的
  • 可以做黄金期权的网站创建自己的网站