synchronized的原理及应用

synchronized原理详解(通俗易懂超级好) 目标 【理解】synchronized底层原理 【掌握】synchronized 的用法 目录目标一、synchronized原理1.1 原子性1.2 可见性1.3 有序性1.4 可重入性二、synchronized 的用法三、synchronized 的底层原理3.1 对象头在JVM中存储的形式3.1.1 对象头3.1.2 对象实例数据3.1.3 对齐填充3.2 Monitor3.3 synchronized锁的优化3.3.1 synchronized锁的状态3.3.2 偏向锁3.3.3. 轻量级锁3. 阅读详情

概述

在之前的一篇文章《“Java内存模型及其原理” 》这篇文章中,曾经介绍过synchronized关键字的作用,解决的是多个线程之间访问资源的同步性,保证被synchronized修饰的代码具有原子性。因而在本篇文章将会深入了解synchronized的使用方式以及原理。

使用

synchronized的使用方法主要有如下三种:

- synchronized的使用方式
	- 修饰实例方法
	- 修饰代码块
	- 修饰静态方法

修饰实例方法

作用:对当前实例对象加锁,进入同步代码前要获取当前实例对象的锁。

synchronized void method() {
  //业务代码
}

结合"Java内存模型及其原理"中"缓存导致可见性问题"中的实例代码:

public class Test {
  private static long count = 0;
  private void add10K() {
    int idx = 0;
    while(idx++ < 10000) {
      count += 1;
    }
  }
  public static long calc() throws InterruptedException {
    final Test test = new Test();
    // 创建两个线程,执行add()操作
    Thread th1 = new Thread(()->{
      test.add10K();
    });
    Thread th2 = new Thread(()->{
      test.add10K();
    });
    // 启动两个线程
    th1.start();
    th2.start();
    // 等待两个线程执行结束
    th1.join();
    th2.join();
    return count;
  }
  
  public static void main(String[] args) throws InterruptedException {
	System.out.println(calc());
  }
}

在《“Java内存模型及其原理”》这篇文章中我们讲了,上述代码最后执行的结果是处于10000到20000之间的一个数字,但通过synchronized关键字对add10K()进行修饰后:

package thread;

public class Test {
  private static long count = 0;
  //使用synchronized关键字修饰add10K
  private synchronized void add10K() {
    int idx = 0;
    while(idx++ < 10000) {
      count += 1;
    }
  }
  public static long calc() throws InterruptedException {
    final Test test = new Test();
    // 创建两个线程,执行add()操作
    Thread th1 = new Thread(()->{
      test.add10K();
    });
    Thread th2 = new Thread(()->{
      test.add10K();
    });
    // 启动两个线程
    th1.start();
    th2.start();
    // 等待两个线程执行结束
    th1.join();
    th2.join();
    return count;
  }
  
  public static void main(String[] args) throws InterruptedException {
	System.out.println(calc());
  }
}

从概念角度上,我们很容易理解,在加入synchronized之后只有一个线程能够进入方法add10K()中,其他方法会在该位置阻塞,因而最终执行结果一定是正确的,最终的执行结果一定是20000。

但从原理层面上讲,增加了synchronized到底发生了什么❓ ❓

add10K()被synchronized 修饰后发生了什么??

要解决这个问题,我们首先需要从JVM角度,上述代码经过synchronized修饰后发生了什么变化。

执行javap -c -s -v -l .\Test.class生成Test类对应的字节码文件如下(仅仅节选了add10K()方法部分):

image.png

经过synchronized修饰的方法会增加增加一个ACC_SYNCHRONIZED标识,该标识会指明该方法是一个同步方法。当JVM在执行有ACC_SYNCHRONIZED标识的同步方法时, 会按照同步的策略进行调用。

当然除了直接修饰方法外,synchronized也可以用来修饰代码块。

修饰静态方法

作用:给当前所有类加锁,会作用于当前所有类的实例对象,进入同步代码前要获取当前Class的锁。

synchronized static void method() {
//业务代码
}

由于synchronized静态方法和synchronized实例方法加锁的是不同的对象,因而对于两个不同的线程可以一个执行synchronized修饰的静态方法,一个执行synchronized修饰的实例方法,两者不会发生互斥。

我们还是一一段简单的代码为例

public static synchronized int add() {
	  int count = 0;
	  while(count <= 10000) {
		  count += 1;
	  }
	  return count;
  }

同样的add()方法在经过synchronized修饰之后,可以保证是线程安全的。

从jvm层面看,增加了synchronized到底发生了什么??

静态add()被synchronized` 修饰后发生了什么??

执行javap -c -s -v -l .\Test.class生成Test类对应的字节码文件如下(仅仅节选了add()方法部分):

image.png

很明显,和前面修饰实例方法一样,经过synchronized修饰的方法会增加一个ACC_SYNCHRONIZED标识,在JVM层面上,保证add()方法的同步调用。

修饰代码块

作用:指定加锁对象,对给定对象/类加锁。synchronized(this|object) 表示进入同步代码库前要获得给定对象的锁 。synchronized(类.class) 表示进入同步代码前要获得 当前 class 的锁。

synchronized(this) {
  //业务代码
}
或者
//加类锁
synchronized(Test.class) {
  //业务代码
}

同样通过synchronized修饰代码块,我们也可以解决前边add10K()存在的线程安全问题:

 public void add10K() {
    int idx = 0;
    synchronized (this) {
        while(idx++ < 10000) {
            count += 1;
        }
     }
  }

从概念上讲,通过synchronized修饰while循环之后,整个while循环的加法操作就相当于是一个原子操作,只有获取到Test对象锁的线程才能进入执行,其他线程会被阻塞,最终执行结果必然相当于执行两边的加法操作,最终结果必然就是20000喽。

同样的,从jvm层面看,它有发生了什么呢?

被synchronized修饰的代码块发生了什么?

同样的我们执行javap -c -s -v -l .\Test.class生成Test类对应的字节码文件如下(仅仅节选了add10K()方法部分):

image.png

我们可以看到,synchronized修饰的代码块和修饰方法时,作用的机理是不同的(其实也非常容易理解,因为修饰的代码块,没法用标识符来进行标识,只能通过插入指令的形式来实现同步):

通过synchronized修饰的代码块中会增加两条指令monitorenter指令和monitorexit指令,其中 monitorenter 指令指向同步代码块的开始位置,monitorexit 指令则指明同步代码块的结束位置。( 当然我们例子中由于synchronized修饰的是while语句块,可能存在判断分支,因而插入了两条monitorexit来保证在每种分支条件下都能正确执行。)

那这两条指令有什么用呢?

简单来说,当执行monitorenter时,会尝试获取对象的锁,如果锁的计数器为 0 则表示锁可以被获取,获取后将锁计数器设为 1 也就是加 1。

在执行 monitorexit 指令后,将锁计数器设为 0,表明锁被释放。如果获取对象锁失败,那当前线程就要阻塞等待,直到锁被另外一个线程释放为止。

扩展:Java6及以上版本对synchronized的优化

我们再深入思考下,synchronized在加锁和解锁的过程中发生了什么呢❓ ❓

这个问题,比较复杂,在Java6之前,synchronized由于所用的锁都是重量级锁,效率较极低,因而为了提高synchronized的效率,引入了适应性自旋、锁消除、偏向锁、轻量级锁、重量级锁等措施来对synchronized进行优化。

从对象头的Mark Word说起

我们知道,其实加锁的本质实际上加锁的对象头写入当前线程的id。 而实际写入的位置就是在对象的Mark word部分,而实际填写的方式就是通过CAS来实现的。

Mark Word用于存储对象自身运行时的数据,如HashCode,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID等等,占用的空间大小与虚拟机位长一致(32位JVM -> MarkWord是32位,64位JVM->Mark Word是64位)。

Mark Word会用不同的标记来标识不同的对象状态(比如未被加锁、轻量级锁、重量级锁等状态):

image.png

此时可能会有小伙伴会有疑问了:不同级别的锁时如何转换的呢?

这就涉及到了锁的升级。

锁的升级

为了便于理解,我们设想一种场景来模拟锁的升级过程,整个过程如下图所示:

image.png

该开始的时候只有一个线程T1运行,此时T1进入同步代码块时:

  • 首先会进行逃逸分析,如果堆上的数据不会逃逸被其他线程访问到,那么就可以认为它是栈上的数据,是线程安全的,就会转而进行锁消除操作,忽略所有同步措施直接运行。

如果有数据逃逸的情况发生,此时就会进入偏向锁状态,当有其他线程如T2竞争同步代码时,此时偏向锁会失效,转而升级为轻量级锁。当然在处于偏向锁状态的对象,在收到计算唯一性哈希码请求(执行hashCode()方法)时,会直接膨胀为重量级锁。

当然轻量级锁也不是最终的锁状态,如果有超过两个线程比如又加入第三个线程T3来竞争同步资源,锁就会膨胀,最终就会变成重量级锁。

上边的整个过程,就是锁的升级过程,上面提到了好几种类型的锁,直接看有些迷糊,因此下边,我们按照不同锁的类型,来解决不同锁的加锁解锁的过程,已经应用的时机。
首先,我们先讲解一下,锁消除的过程。

锁消除

什么叫做锁消除呢?

首先用一下专业术语来解释一下:

锁消除就是指虚拟机即时编译器在运行时,对一些代码要求同步,但对被检测到的不可能存在共享数据竞争的锁进行消除。

用大白话解释,锁消除就是说把“锁去掉”,但我们不可能见到一个锁就把它给“去掉”,这加锁就没有任何意义了,因而了解锁消除的场景和时机就极为重要了,我们只能在运行期间,把那些不可能存在共享数据竞争的锁进行消除。

如何判断线程是否具有共享数据竞争呢??

这就需要逃逸分析技术做支持喽,在进行逃逸分析后如果发现,如果堆上的数据都不会逃逸被其他线程访问到,那么就可以把它们当做栈上数据对待,认为它们是线程私有的,同步加锁自然无需再进行。

当然,如果进行逃逸分析之后,发现确实存在数据逃逸问题,此时就需要加锁。

偏向锁

什么是偏向锁呢?

简单来说,这个锁会偏向第一个获取它的线程,如果在接下来的执行过程,该锁一直没有被其他锁获取,则持有偏向锁的线程将永远不需要再进行同步,也就是说偏向锁不需要解锁,因而偏向锁的效率极高。

为什么要这样做呢? 因为经验表明, 其实大部分情况下, 都会是同一个线程进入同一块同步代码块的,这也是为什么会有偏向锁出现的原因。

在Jdk1.6中, 偏向锁的开关是默认开启的, 适用于只有一个线程访问同步块的场景。

加锁:

对象从无锁到获取到偏向锁再到重入锁整个过程,如下图所示:

image.png

当一个对象处于无锁状态时,它的偏向锁标志为0,标志位为01,hashcode为空(计算过hashCode的对象无法进入偏向模式)。

当锁对象第一次被线程获取的时候,虚拟机会把对象头的偏向模式设置为1,表示进入偏向模式,同时会通过CAS操作获取到这个锁的线程ID并记录到Mark Word中。如果操作成功,持有偏向锁的线程以后进入这个锁相关的同步块时,只需要比较偏向锁中的线程ID是否和当前ID一致即可,如果相同的话,就不再需要任何同步操作,直接执行同步代码。

偏向锁的撤销时机:

偏向锁使用了一种等到竞争出现才释放锁的机制, 所以当其他线程尝试竞争偏向锁时, 持有偏向锁的线程才会释放锁。

另一点,由于当时使用偏向锁时,Mark Word的大部分空间都用来存储持有锁的线程ID了,因而当某个对象处于偏向锁模式,又收到需要计算其一致性哈希码请求时,偏向锁会立即撤销,并膨胀为重量级锁。同时已经计算过一致性哈希码的对象无法进入偏向模式。

具体撤销过程如下:

偏向锁的撤销需要等到全局安全点(在这个时间点上没有正在执行的字节码). 首先会暂停持有偏向锁的线程, 然后检查持有偏向锁的线程是否存活, 如果线程不处于活动状态, 则将锁对象的对象头设置为无锁状态; 如果线程仍然活着, 则锁对象的对象头中的MarkWord和栈中的锁记录要么重新偏向于其它线程要么恢复到无锁状态, 最后唤醒暂停的线程(释放偏向锁的线程)。

轻量级锁

当出现有两个线程来竞争锁的话, 那么偏向锁就失效了, 此时锁就会膨胀, 升级为轻量级锁。

加锁:

从偏向锁或者无锁状态转成轻量级锁的过程如下:

image.png

在代码进入同步块时,如果此同步对象没有被锁定,虚拟机首先将在当前线程的栈帧中建立起一个名为锁记录(Lock record)的空间,用于存储当前Mark Word的拷贝(以Displaced为前缀),然后虚拟机将尝试通过CAS操作把对象的Mark Word转变为00,表示此对象处于轻量级锁定状态中。如果更新失败,则说明存在一条线程与当前线程竞争,此时虚拟机会首先检查对象的Mark Word是否指向当前线程的栈帧,如果是,说明当前线程已经拥有了这个对象的锁,直接重入,进入同步代码块直接执行;否则,说明这个锁对象已经被其他线程抢占了。

当有出现两条以上的线程争用同一个锁的情况,那轻量级锁就不再有效,会膨胀为重量级锁。

解锁:

轻量级锁解锁时, 会使用原子的CAS操作将当前线程的锁记录替换回到对象头, 如果成功, 表示没有竞争发生; 如果失败, 表示当前锁存在竞争, 锁就会膨胀成重量级锁。

重量级锁

重量级锁的实现就比较复杂,需要借助前边介绍的monitorenter和monitorexit指令,当加锁时,线程会尝试获取加锁对象的monitor(每一个对象都内置了一个monitor对象,由C++实现),获取成功后开始执行同步代码,获取失败进入同步队列,当执行到monitorexit指令时,释放对象锁,并唤醒同步队列中的阻塞线程。整个执行逻辑如下图所示:

image.png

锁的小结

最后,简单总结一下锁优缺点:

锁优点缺点适用场景
偏向锁加锁和解锁不需要额外的消耗, 和执行非同步代码方法的性能相差无几.如果线程间存在锁竞争, 会带来额外的锁撤销的消耗.适用于只有一个线程访问的同步场景
轻量级锁竞争的线程不会阻塞, 提高了程序的响应速度如果始终得不到锁竞争的线程, 使用自旋会消耗CPU追求响应时间, 同步快执行速度非常快
重量级锁线程竞争不适用自旋, 不会消耗CPU线程堵塞, 响应时间缓慢追求吞吐量, 同步快执行时间速度较长

总结

本篇文章主要讲了synchronized的三个应用方式:修饰实例方法、修饰静态方法、修饰代码块,并且针对每种方式都从JVM角度讲解了其实现的底层原理。在扩展部分则详细讲解了Java6对synchronized的优化措施,以及底层的原理。

参考

  1. 《深入理解JVM虚拟机》
  2. 《Java并发实战》
  3. 《Java并发编程实战》
  4. Java6及以上版本对synchronized的优化
如何区分Info与CoWoS封装? 这篇文章主要从Info、CoWoS封装的定义、Interposer的种类以及Info、CoWoS封装的种类三方面进行了介绍,希望读者能够有所收获 阅读详情

相关推荐

Nacos2.X 源码分析:为订阅方推送、服务健康检查、集群数据同步、grpc客户端服务端初始化

而Nacos2.X 从http请求改为了grpc请求的方式了,在健康检查这方面就是基于长连接来实现的。客户端发送心跳是在构建grpc连接时会有一个线程每隔5s发送一次,NacosClient端发送心跳的代码在。我们能大致猜测:当一个服务的实例进行了更新,那么是不是应该推送给所有订阅了该服务的客户端?当我订阅了某个服务,是不是应该将该服务信息推送给我?在服务实例检查检查流程中,如果出现了要注销的服务实例就会发布。在服务发现时,进行订阅服务的最后会发布一个。服务注册与服务订阅流程中发布的事件最终会被。

qq_44027353的博客 1594

synchronized详解

对synchronized的了解 synchronized 关键字解决的是多个线程之间访问资源的同步性,synchronized关键字可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行。 在 Java 早期版本中,synchronized 属于 重量级锁,效率低下。 为什么呢? 因为监视器锁(monitor)是依赖于底层的操作系统的 Mutex Lock 来实现的,Java 的线程是映射到操作系统的原生线程之上的。如果要挂起或者唤醒一个线程,都需要操作系统帮忙完成,而操作系统实现线程之间的切换时.

fwdwqdwq的博客 4792

ROS2前置基础教程 | 使用CMakeLists.txt编译ROS2节点

答案是有的,那就是cmake工具。cmake通过调用CMakeLists.txt直接生成Makefile。 2.新建CMakeLists.txt 在新建,输入下面内容。 3.编译代码 我们一般会创建一个新的目录,运行cmake并进行编译,这样的好处是不会显得那么乱。 创建好文件夹,接着运行cmake指令,代表到上级目录找。 运行完cmake你应该可以在build目录下看到cmake自动生成的Makefile了,接着就可以运行make指令进行编译 运行完上面的指令,就可以在build目录下发现节点了。ROS2

生活不止眼前的苟且 1万+

深入研究 synchronized 同步锁 作用于 静态方法 和 非静态方法 的 区别

1.前言 众所周知, synchronized 是同步锁 ,虽然在底层又细分了无锁、偏向锁、轻量级锁、自旋锁 以及重量级锁 机制, 这些底层锁知道一下原理即可 ,【想要 了解 这篇 博文 有 解释 : https://blog.youkuaiyun.com/u013256816/article/details/51204385 】 我这篇随笔专门研究与总结 关于 synchronized 加 在 同一个类里的 静态 和非静态 方法前 有什么不一样的影响 。 这都是因为我看到的一道题引起的: 答案是 BE 为什么? 查

u013750244的博客 1149

数据分析之AB测试基础知识

在 A/B 测试中,零假设是两组的指标是相同的,当假设检验推断出两组指标不同,但事实上两组指标相同时,就是第一类错误。

qq_45727498的博客 561

【漏洞复现】Palo Alto Networks PAN-OS GlobalProtect 命令注入漏洞 CVE-2024-3400

在特定PAN-OS版本和不同功能配置下,未经身份验证的攻击者可能利用此漏洞在防火墙上以root权限执行任意代码。技术文章仅供参考,任何个人和组织使用网络应当遵守宪法法律,遵守公共秩序,尊重社会公德,不得利用网络从事危害国家安全、荣誉和利益,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。本文所提供的工具仅用于学习,禁止用于其他!poc如下,注入点在Cookie中,将其中的DNSlog地址替换为你的dnslog地址,借助DNSLOG来复现,可以使用http://dnslog.pw/

失心少年 1226

synchronized原理及其应用(详细且认真)

1. 概述 在jdk1.6之前,synchronized是基于底层操作系统的Mutex Lock实现的,每次获取和释放锁都会带来用户态和内核态的切换,从而增加系统的性能开销。在锁竞争激烈的情况下,synchronized同步锁的性能很糟糕。JDK 1.6,Java对synchronized同步锁做了充分的优化,甚至在某些场景下,它的性能已经超越了Lock同步锁 我们先来讲解synchronized...

米奇罗 2555

【系统架构设计师】2025年下半年真题论文回忆版及写作要点

本文摘要围绕云原生数据库、性能测试、无服务器架构和秒杀场景等关键技术进行论述。云原生数据库通过容器化、微服务和自动化运维实现弹性扩展;性能测试需要规划测试场景并关注响应时间等关键指标;无服务器架构以事件驱动为核心,简化开发流程;秒杀场景需组合运用扩容、缓存、限流等技术应对高并发。这些技术方案为构建现代高可用系统提供了重要参考。

数据知道的博客 6160

synchronized作用静态方法和非静态方法区别

synchronized作用于非静态方法,实际上是对当前实例对象加锁,就是说如果一个实例对象的非静态同步方法获取锁后,该实例对象的其他非静态同步方法必须等待获取锁的方法释放锁后才能获取锁,可是别的实例对象的非静态同步方法因为跟该实例对象的非静态同步方法用的是不同的锁,所以毋须等待该实例对象已获取锁的非静态同步方法释放锁就可以获取他们自己的锁。解释:因为虽然是一个对象调用,但是两个方法的锁类型不同,调用的静态方法实际上是类对象在调用,即这两个方法产生的并不是同一个对象锁,因此不会互斥,会并发执行。

m0_46145044的博客 306

ROSTEA软件下载及情感分析详细操作教程(附网盘链接)

原ROST虚拟团队出品的ROST系列文本内容挖掘分析平台,是辅助人文社会科学研究的免费计算平台。该软件可以实现文本预处理、分字、分词、词性识别、特殊名词抽取、词频统计、英文词频统计、情感计算、分类算法、聚类算法等一系列文本挖掘,是人文社科研究和论文写作的一把利器。该软件用户量超过一万人,遍布海内外100多所大学,包括剑桥大学、日本北海道大学、北京大学、清华大学、香港城市大学、澳门大学等众多高校。关于ROSTCM6的安装介绍可以参考之前的文章ROSTCM6软件下载及语义网络分析详细操作教程ROST EA。

m0_64336780的博客 1万+

threejs中使用Reflector实现出倒影效果,并实现背景透明的效果(Reflector镜面背景透明, 倒影弱化)

在项目中遇到要实现倒影效果,threejs给我们提供了Reflector,可以轻松完成镜面效果,实现倒影。但背景不透明;并且反射出的倒影太亮了;网上没搜到解决方案, 自己修改了下源码实现了想要的效果,做个记录...

weixin_40856652的博客 5722

synchronized原理_synchronized原理及其应用

在jdk1.6之前,synchronized是基于底层操作系统的 Mutex Lock 实现的,每次获取和释放锁都会带来 用户态和内核态的切换 ,从而增加系统的 性能开销 。在锁竞争激烈的情况下,synchronized同步锁的性能很糟糕。 JDK 1.6 ,Java对synchronized同步锁做了 充分的优化 ,甚至在某些场景下,它的性能已经超越了Lock同步锁我们先来讲解synchroni...

weixin_39618730的博客 121

我用 Python 监听了自己的键盘,生成击键热力图,看看每天到底在“摸鱼”还是“搬砖”?

数据采集(监听)、持久化(I/O)与可视化展示,必须是三个完全独立的模块,这符合单一职责原则。在多线程读写 Python 字典时,锁住的时间要尽可能短,防止 I/O 线程把高频的监听线程阻塞住。这类涉及底层的代码与“键盘记录木马”只有一线之隔。永远不要把击键记录通过网络上传,所有数据必须localhost消化。人脑对枯燥的 JSON 日志是不敏感的,但对颜色和空间极其敏感。这也是为什么 Prometheus + Grafana 是标配。使用ctypes。

BUG猿的博客 194

synchronized和volatile的原理及应用

synchronized和volatile

一个想交朋友的陌生人 1207

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

简单说一说Synchronized的实现原理与应用

啊哈,Synchronized一点都说不出来?爬

u011232863的博客 795

【JUC】——synchronized应用、作用及实现原理

前言 在 Java 中,关键字 synchronized可以保证在同一个时刻,只有一个线程可以执行某个方法或者某个代码块(主要是对方法或者代码块中存在共享数据的操作),同时我们还应该注意到synchronized另外一个重要的作用,synchronized可保证一个线程的变化(主要是共享数据的变化)被其他线程所看到(保证可见性,完全可以替代Volatile功能),这点确实也是很重要的。 三种应...

我爱吃土豆 6632

synchronized的实现原理与应用

synchronized的实现原理与应用 在多线程并发编程中synchronized一直是元老级角色,很多人都会称呼它为重量级锁。但 是,随着Java SE 1.6对synchronized进行了各种优化之后,有些情况下它就并不那么重了。本文 详细介绍Java SE 1.6中为了减少获得锁和释放锁带来的性能消耗而引入的偏向锁和轻量级 锁,以及锁的存储结构和升级过程。 先来看下利用synchronized实现同步的基础:Java中的每一个对象都可以作为锁。具体表现 为以下3种形式。 ·对于普通同步方法,

qq_40826814的博客 132

Java中synchronized的实现原理与应用

Java中的每一个对象都可以作为锁,而在Synchronized实现同步的几种方式中分别为: 普通同步方法:锁是当前实例对象 静态同步方法:锁是当前类的Class对象 同步方法块:锁是Synchronized括号里配置的对象 任何一个对象都一个Monitor与之关联,当且一个Monitor被持有后,它将处于锁定状态。Synchronized在JVM里的实现都是基于进入和退出Monitor对象来实现方

正在加载中 3万+

Java并发编程——synchronized的实现原理与应用

是 Java 提供的一种内置关键字,用于实现线程同步,确保多线程环境下对共享资源的互斥访问。它是 JVM 层面的机制,简单易用,但底层实现较为复杂。机制实现的 Monitor 是对象头(Object Header)中的一部分,包含锁信息。JVM 通过字节码指令和锁优化来保证线程安全。它简单,但需注意死锁风险(多锁嵌套)。机制优化性能,避免不必要的开销。锁信息存储在对象头中(Mark Word,64 位中约占 64 位用于锁状态)。的锁不是简单的互斥锁,而是通过。

weixin_44547668的博客 591

synchronized 应用分析和原理

目录应用分析synchronize作为多线程关键字,是一种同步锁 ,三种应用方式1. 修饰代码块2. 修饰普通方法2.1. 针对同一实例对象2.2. 针对不同实例对象3. 修饰static方法3.1. 针对同一实例对象3.2. 针对不同实例对象原理synchronized的锁的原理Java对象头monitor 应用分析 synchronize作为多线程关键字,是一种同步锁 ,三种应用方式 修饰代...

zhaoyangfang的专栏 286

synchronized 的实现原理与应用

&nbsp;&nbsp;&nbsp;&nbsp;synchronized 是多线程并发编程中的一员,被称为重量级锁,但在 Java SE 1.6 对 synchronized 进行了各种优化,引入偏向锁和轻量级锁,减少了获取锁和释放锁带来的性能消耗。 synchronized 实现同步的基础 &nbsp;&nbsp;&nbsp;&nbsp;Java 中的每一个对象都可以作为锁。具体表现为以...

p7+的博客 1378

Synchronized的实现原理与应用

1.线程的安全性问题 Synchronized原理与使用 内置锁 互斥锁 修饰普通方法——内置锁就是当前类的实例 修饰静态方法——内置锁就是当前的class字节码对象 修饰代码块方法——内置锁为传入的参数 字节码层面分析Synchronized的实现原理 2.活跃性问题 死锁——哲学家就餐问题。 饥饿——线程优先级过低,导致一直拿不到资源,一直无法执行,就会处于饥饿状态。...

weixin_43847987的博客 258

synchronized的应用和实现原理

一文搞定synchronized的实现原理

merrc的博客 843

synchronized的实现原理和应用

synchronized关键字实现原理和应用,wair notify notifyAll解析

北堂飘霜_记录 260

synchronized的三种应用方式jvm中synchronized的实现原理,什么是对象头

synchronized synchronsized三种应用方式:synchronized作用于实例方法,sychronized作用于静态方法,synchronized同步代码块 线程安全是并发编程的重要关注点,造成线程安全问题的原因,有共享数据,多个线程操作共享数据。 解决方式,保证同一时刻只有一个线程操作数据,其他线程必须在线程处理完成之后在进行,访问互斥 synchronized保证统一时刻...

qq_41174684的博客 815
上一篇: Java内存模型及其原理
下一篇: skywalking agent插件开发过程中各种拦截点的写法
vcjmhg
博客等级 码龄11年 27粉丝 94原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值