并发编程原理与实战(二十六)深入synchronized底层原理实现

Java 并发编程面试二 synchronized 是和 if、else、for、while 一样的关键字,ReentrantLock 是类,1、Callable 规定(重写)的方法是 call(),Runnable 规定(重写)的方法是 run()。2、Thread1 的构造方法、静态块是 Thread2 调用的,Thread1 的 run()方法是。1、Thread2 的构造方法、静态块是 main 线程调用的,Thread2 的 run()方法是。所以 CyclicBarrier 能处理更为复杂的业务场景,比如如果。 阅读详情

锁在保证线程安全的过程中起着关键性的作用。在第二篇文章和第十五篇文章中,我们对锁以及synchronized关键字已经有了一定的了解。本文对synchronized进一步学习,深入分析其底层的实现原理。

synchronized使用

先来看看官方对synchronized使用说明。

同步语句

The synchronized statement (§14.19) computes a reference to an object; it then
attempts to perform a lock action on that object's monitor and does not proceed
further until the lock action has successfully completed. After the lock action has
been performed, the body of the synchronized statement is executed. If execution
of the body is ever completed, either normally or abruptly, an unlock action is
automatically performed on that same monitor.

当执行 synchronized 修饰的语句块时,首先计算对象的引用,随后尝试‌在该对象的监视器‌上执行锁定操作,并在锁定成功后才继续执行后续代码。如果同步块内的代码执行完成,无论正常结束或异常中断,在该监视器上将会自动执行一个解锁操作。

同步方法

A synchronized method (§8.4.3.6) automatically performs a lock action when it is
invoked; its body is not executed until the lock action has successfully completed. If
the method is an instance method, it locks the monitor associated with the instance
for which it was invoked (that is, the object that will be known as this during
execution of the body of the method). If the method is static, it locks the monitor
associated with the Class object that represents the class in which the method is
defined. If execution of the method's body is ever completed, either normally or
abruptly, an unlock action is automatically performed on that same monitor.

一个synchronized修饰符的方法被调用时将会执行一个锁定操作,synchronized代码块中的代码不会执行直到锁定操作成功完成。如果方法是一个实例方法,锁定的是当前实例关联的监视器(即方法体内的 this 对象)。如果方法是一个静态方法,锁定的该方法所属类的 Class 对象关联的监视器。如果方法体执行完成,无论正常结束或异常中断,在该监视器上将会自动执行一个解锁操作。

基于上述语法说明,才有了常见的synchronized的三种用法,回顾下代码,如下:

public class SynchronizedTest {
    public static void main(String[] args) {
        System.out.println("synchronized class");
    }
	//修饰普通方法
    public synchronized void output(String name) {
        for(int i=0; i<5; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(name);
        }
    }
	//修饰代码块
    public void output2(String name) {
        synchronized(this) {
            for(int i=0; i<5; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(name);
            }
        }
    }
	//修饰静态方法
    public static synchronized void output3(String name) {
        for(int i=0; i<5; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(name);
        }
    }
}

‌死锁处理机制

在使用synchronized加锁时,开发者并不需要代码显示的控制死锁的问题。

The Java programming language neither prevents nor requires detection of
deadlock conditions. Programs where threads hold (directly or indirectly) locks
on multiple objects should use conventional techniques for deadlock avoidance,
creating higher-level locking primitives that do not deadlock, if necessary.
Other mechanisms, such as reads and writes of volatile variables and the use
of classes in the java.util.concurrent package, provide alternative ways of
synchronization.

Java编程语言既不阻止也不要求检测‌死锁现象。若线程直接或间接持有多个对象锁,开发者需采用以下策略:使用常规的死锁避免技术,必要时创建‌高级无死锁锁原语‌。‌替代同步方案‌的其他机制,‌比如volatile 变量‌的读写操作,java.util.concurrent 包中的并发工具类,提供了其他可选的同步方案。

底层实现原理

用到synchronized关键字就绕不开对象的监视器‌。关于对象监视器‌,或许还有很多疑问。

(1)什么是对象的监视器‌?

(2)如何查看对象监视器‌的状态信息?

(3)synchronized是如何上锁和解锁的?我们已经学习了Lock相关的锁,这类锁上锁和解锁都有显式Lock和unLock操作,那么synchronized是如何实现的?

(4)synchronized既然是一个独占锁,那么其他抢锁的等待者记录在哪里?

(5)synchronized既然可重入,那么重入计数记录在哪里?

(6)持有监视器锁的线程线程信息记录在哪里?

…

针对这些问题,只有深入其底层实现才能搞懂。

对象监视器锁

首先,先来看看什么是对象的监视器‌,下面是官方文档关于对象监视器的描述:

The Java programming language provides multiple mechanisms for
communicating between threads. The most basic of these methods is
synchronization, which is implemented using monitors. Each object in Java is
associated with a monitor, which a thread can lock or unlock. Only one thread at
a time may hold a lock on a monitor. Any other threads attempting to lock that
monitor are blocked until they can obtain a lock on that monitor. A thread t may
lock a particular monitor multiple times; each unlock reverses the effect of one
lock operation.

java编程语言提供了多种线程间通信的机制,通过监视器实现的同步是最基础的一种方法,这个是实现线程间同步的核心机制。Java中每个对象都有一个关联的监视器对象,线程可以对该对象进行加锁(lock)和解锁(unlock)操作。同一时刻仅允许一个线程持有监视器对象,其他尝试锁定该监视器的线程将被阻塞,直至获取锁成功。一个线程可多次锁定同一监视器对象,每次解锁操作抵消一次锁定。

由此可见,基于监视器实现的锁具有独占性和可重入性(多次上锁)。而synchronized正是基于对象监视器实现的锁。

查看对象监视器的状态信息

了解了什么是对象监视器之后,接下来解决如何查看对象监视器‌的状态信息这个问题。下面的代码用主线程和一个子线程分别不断地调用synchronized修饰的output()方法,然后输出线程的ID。

public class SynchronizedTest {
    public static void main(String[] args) {
        new Thread(() -> {
            for (; ; ) {
                output("t1 thread running");
            }
        }, "t1").start();

        for (; ; ) {
            output("main thread running");
        }
    }

    public static synchronized void output(String name) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(name + " thread tid " + Thread.currentThread().getId() + ", thread nid " + getOsThreadId(Thread.currentThread()));
    }

    public static long getOsThreadId(Thread thread) {
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        return threadMXBean.getThreadInfo(thread.getId()).getThreadId();
    }
}

输出结果

main thread running thread tid 1
main thread running thread tid 1
t1 thread running thread tid 23
t1 thread running thread tid 23
...

输出线程ID的目的是,接下来使用jstack命令查看线程堆栈信息和对象监视器的状态时用到,根据线程ID查找对应的堆栈信息。在windows的任务管理中找到该程序的PID号为10776,然后使用jstack -l 10776命令查看Java进程的线程堆栈及锁状态详情,也可以通过jstack -l 10776 > thread_dump.log命令输出到thread_dump.log文件中。。我们摘取相main线程和t1线程的堆栈信息来分析,如下图:
在这里插入图片描述
在这里插入图片描述

从main线程和t1线程的堆栈信息可以看出:

(1)线程名称和线程ID和上述程序输出结果一致。

(2)main线程在调用output()方法进入TIMED_WAITING睡眠状态时,仍然处于持有锁的状态,所以此时的t1线程处于BLOCKED阻塞状态,等待main线程释放监视器锁。这个符合我们的程序逻辑。

(3)main线程的堆栈信息中的locked <0x0000000754d98f08>是main线程持有的监视器地址,进一步说明main线程正持有监视器锁。

(4)t1线程的堆栈信息中的waiting to lock <0x0000000754d98f08>是t1线程正在等待的监视器地址,进一步说明t1线程正等待监视器锁。

显式隐式获取监视器锁

解决了什么是对象监视器以及如何查看对象监视器‌的状态信息这两个问题后,接下来分析synchronized是如何上锁和解锁的。我们使用javap -c SynchronizedTest.class命令将上述文章开头的代码对应的class文件反编译成字节码指令。

C:\Program Files\Java\jdk-21\bin>javap -verbose SynchronizedTest.class
...
{
  public com.demo.SynchronizedTest();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 2: 0
  ...

  public synchronized void output(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: (0x0021) ACC_PUBLIC, ACC_SYNCHRONIZED
    Code:
      stack=2, locals=4, args_size=2
         0: iconst_0
         1: istore_2
         2: iload_2
         3: iconst_5
         4: if_icmpge     34
         7: ldc2_w        #21                 // long 1000l
        10: invokestatic  #23                 // Method java/lang/Thread.sleep:(J)V
        13: goto          21
        16: astore_3
        17: aload_3
        18: invokevirtual #31                 // Method java/lang/InterruptedException.printStackTrace:()V
        21: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
        24: aload_1
        25: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        28: iinc          2, 1
        31: goto          2
        34: return
      Exception table:
         from    to  target type
             7    13    16   Class java/lang/InterruptedException
      LineNumberTable:
        line 8: 0
        line 10: 7
        line 13: 13
        line 11: 16
        line 12: 17
        line 14: 21
        line 8: 28
        line 16: 34
      StackMapTable: number_of_entries = 4
        frame_type = 252 /* append */
          offset_delta = 2
          locals = [ int ]
        frame_type = 77 /* same_locals_1_stack_item */
          stack = [ class java/lang/InterruptedException ]
        frame_type = 4 /* same */
        frame_type = 250 /* chop */
          offset_delta = 12

  public void output2(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=6, args_size=2
         0: aload_0
         1: dup
         2: astore_2
         3: monitorenter
         4: iconst_0
         5: istore_3
         6: iload_3
         7: iconst_5
         8: if_icmpge     40
        11: ldc2_w        #21                 // long 1000l
        14: invokestatic  #23                 // Method java/lang/Thread.sleep:(J)V
        17: goto          27
        20: astore        4
        22: aload         4
        24: invokevirtual #31                 // Method java/lang/InterruptedException.printStackTrace:()V
        27: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
        30: aload_1
        31: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        34: iinc          3, 1
        37: goto          6
        40: aload_2
        41: monitorexit
        42: goto          52
        45: astore        5
        47: aload_2
        48: monitorexit
        49: aload         5
        51: athrow
        52: return
      Exception table:
         from    to  target type
            11    17    20   Class java/lang/InterruptedException
             4    42    45   any
            45    49    45   any
      ...

  public static synchronized void output3(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: (0x0029) ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
    Code:
      stack=2, locals=3, args_size=1
         0: iconst_0
         1: istore_1
         2: iload_1
         3: iconst_5
         4: if_icmpge     34
         7: ldc2_w        #21                 // long 1000l
        10: invokestatic  #23                 // Method java/lang/Thread.sleep:(J)V
        13: goto          21
        16: astore_2
        17: aload_2
        18: invokevirtual #31                 // Method java/lang/InterruptedException.printStackTrace:()V
        21: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
        24: aload_0
        25: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        28: iinc          1, 1
        31: goto          2
        34: return
      Exception table:
         from    to  target type
             7    13    16   Class java/lang/InterruptedException
     ...
}
SourceFile: "SynchronizedTest.java"

C:\Program Files\Java\jdk-21\bin>

从上面可以看出,synchronized修饰普通方法和修饰静态方法时,字节码文件方法中会有同步标志 ACC_SYNCHRONIZED,而修饰代码块时使用了生成显式的 monitorenter/monitorexit 指令。ACC_SYNCHRONIZED 是方法的访问标志位,编译时由编译器添加,无需生成显式的 monitorenter/monitorexit 指令。两种上锁和释放锁的方式是有区别的:

(1)当synchronized修饰的普通方法和修饰静态方法时方法被调用时,JVM 检查是否设置ACC_SYNCHRONIZED 标志,若设置了线程会‌隐式尝试获取锁‌:对于实例方法锁对象是当前实例(this);对于静态方法锁对象是当前类的 Class 对象(如 SynchronizedTest.class);获取锁失败时线程进入阻塞状态,直到锁被释放。‌锁释放‌时无论方法正常执行结束还是抛出异常,JVM 均‌自动释放锁‌避免死锁。

(2)当执行synchronized修饰的代码块时,底层通过monitorenter指令进行上锁,我们知道,每个java对象都有一个隐式关联一个监视器(锁),调用monitorenter 指令尝试获取该监视器的所有权;调用monitorexit 指令时释放锁,异常时也会触发释放避免死锁。

阿里巴巴面试题- - -多线程&并发篇(二十六) 再次渡入繁世,人潮汹涌,眼里茫然,信仰永恒,皆为华夏。 阅读详情

相关推荐

ShardingSphere-JDBC-若依框架集成(SpringBoot)

ShardingSphere基础知识、ShardingSphere-JDBC如何集成进若依框架中 使用的是若依框架前后端版本、动态数据源,可自行切换,默认数据源为达梦8代理端,

编程小菜鸟的笔记 8168

八股文--->并发编程

目录 一:并发编程的优点二:并发编程的缺点三:并发编程三要素是什么?四:在 Java 程序中怎么保证多线程的运行安全?四(1)voliate为什么不能保证原子性五:并行和并发有什么区别?六:什么是JMM模型七:什么是多线程,多线程的优劣?八:什么是进程和线程九:进程和线程的区别十:什么是上下文切换 十一:用户线程和非守护线程十二:形成死锁的四个必要条件 十三:如何避免线程死锁 十四:创建线程的四种方式 十五:继承Thread和实现Runnable区别十六:实现Runnable和Callable的区别十七:线

weixin_47188125的博客 2032

DRAM内存模拟持久化设备的方法

由于持久化内存介质NVM技术的发展,越来越多的科研工作者投身到NVM相关的研究当中。但由于目前工业界并没有推出广泛使用的NVM介质设备,所以科研工作都需要自己以现有的条件,模拟NVM设备使用场景。一个简单的方法是:通过修改DRAM模拟器,达到模拟NVM的目的(可以参考:DRAMSim2模拟器分析与应用)。更高端的方式是:在真实系统中,将内存划分出一块儿,用来模拟NVM设备(类似于传统的ramdis

酷炫人笨笨熊 1899

Java 并发编程进阶,从线程池、锁、AQS 到并发容器与性能调优全解析

本文系统梳理了Java并发编程的核心知识点,从并发问题的本质出发,深入剖析了Java内存模型、线程同步机制、锁优化策略等关键技术。主要内容包括:并发问题的根源(共享、竞争、时序)、JMM内存模型三大特性(原子性、可见性、有序性)、volatile和synchronized的使用场景与边界、ReentrantLock与AQS原理、线程池设计理念等。文章特别强调并发编程的工程实践价值,指出线上常见的偶发故障往往与并发控制不当有关,并提供了锁选择、线程池配置等实用建议。通过本文,开发者可以建立完整的并发知识体系,

百锦再的博客 2万+

Ethercat学习-从站源码生成

移植平台GD32F450,从站芯片AX58100

西澳峰的博客 9215

告别unittest!用Pytest+Fixture重构你的Python测试代码(附实战案例)

本文详细介绍了如何从unittest迁移到Pytest框架,重点解析了Pytest的Fixture机制如何提升测试效率和代码简洁性。通过实战案例展示了Pytest在减少代码量、提升调试效率和资源管理方面的优势,帮助开发者重构Python测试代码。

weixin_26749245的博客 206

Java学习第一百二十六部分——锁

Java中的锁机制是实现线程同步、保证数据一致性和避免竞态条件的核心工具,主要分为基础锁和高级锁。本文介绍其详细信息,优化技术,使用对比和选型建议等内容。

2503_92550335的博客 1306

Android系统开机时间分析与优化指南

本文系统阐述了Android开机时间优化的全流程技术方案。首先详细解析了从电源键按下到桌面显示的完整启动流程及关键事件序列,然后介绍了秒表计时、日志分析和自动化脚本三种测量方法。重点从底层和上层两个维度提出了具体优化措施:底层包括编译器优化、内核驱动裁剪和日志精简;上层涵盖系统服务参数调整、应用预优化和功能组件精简。最后提供了验证工具和方法,并强调优化需要在性能、功耗和功能间取得平衡。通过这套系统化方案,可有效提升Android设备的开机速度与用户体验。

学无止境 351

第二十六章 ThreadLocal原理及生产中遇到的坑

ThreadLocal原理及生产中遇到的坑什么是ThreadLocalThreadLocal实现原理ThreadLocal使用场景ThreadLocal常用示例ThreadLocal 实现原理静态内部类的实例化ThreadLocal结构ThreadLocal主要方法剖析几个概念主要方法initialValue方法set方法清除脏的entry替换脏的entryrehash方法get方法remove方法thread.exit()ThreadLocal内存泄漏问题总结2.4 为什么使用弱引用? 什么是Thre.

gonghaiyu的博客 921

【我的Android进阶之旅】解决android应用使用android:persistent属性带来的系统Launcher应用必须重启设备才生效的问题,大幅度提升开发效率

一、问题描述 我们在开发系统级别应用,比如Launcher桌面的时候,会发现有个问题:每次Launcher修改完代码,重新编译之后,安装到android设备上之后,必须重启才会生效。否则就是使用了之前的Launcher版本的内容。而每次重启设备得一分钟左右,太慢了,太影响效率了! 1.1 痛点 每次更新完代码,重新安装之后,必须重启设备才会生效。效率太TM低了! 二、分析问题 经过一轮代码排查,最终发现是因为src\main\AndroidManifest.xml文件中,定义application使用了an

字节卷动 1712

Python 爬虫实战:豆瓣 / IMDB 电影数据抓取(评分 + 剧情 + 演员阵容结构化处理)

在数据为王的时代,电影数据是进行市场分析、推荐系统构建和学术研究的重要资源。豆瓣和 IMDB 作为国内外最具影响力的电影评分和资讯网站,包含了海量高质量的电影数据。本文将带领你从零开始,构建一个健壮的 Python 爬虫,用于抓取豆瓣和 IMDB 的电影信息,并将其中的非结构化数据(如剧情简介、演员列表)进行清洗和结构化处理,最终存储到便于分析的结构化文件(如 CSV)中。

yansideyucsdn的博客 953

并发编程(二十六)-ReentrantLock应用

并发编程(二十六)-ReentrantLock应用

及时当勉励,岁月不待人 298

2024届数字IC秋招-华为机试-数字芯片-笔试真题和答案(五)(含2022年和2023年)

此部分包含华为机试真题,方向是数字芯片,内容详细包括设计、验证、后端等,大部分题目给出参考答案。华为机试都是从题库里抽题目,所以这些题目还是很有参考性的,甚至是完全一样,可以搜到的。(题目内容较多,将分开编写几个文章)

qq_42135020的博客 2081

并发编程篇

一、线程和进程的区别 二、并行与并发的区别 三、创建线程的方式有哪些 四、线程包含了哪些状态,状态之间是如何变化的 五、新建T1,T2,T3 三个线程如何保证他们按顺序执行 六、notify和notifyAll有什么区别 七、Java中的Wait方法和Sleep方法有什么不同 八、如何停止一个正在运行的线程 九、synchronized关键字的底层原理 十、monitor实现的锁

m0_64703222的博客 207

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

深度学习工具包 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")

JAVA并发系列二十六:Java中atomic包下原子操作类总结

原博地址:https://www.javazhiyin.com/18107.html 1. 原子操作类介绍 在并发编程中很容易出现并发安全的问题,有一个很简单的例子就是多线程更新变量i=1,比如多个线程执行i++操作,就有可能获取不到正确的值,而这个问题,最常用的方法是通过Synchronized进行控制来达到线程安全的目的。但是由于synchronized是采用的是悲观锁策略,并不是特别高效的一种解决方案。实际上,在J.U.C下的atomic包提供了一系列的操作简单,性能高效,并能保证线程安全的类去更新基

今天的BUG保熟。 864

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Java并发编程-总结-21-33

二十一、死锁 死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。这是一个严重的问题,因为死锁会让你的程序挂起无法完成任务。 死锁的发生必须满足以下四个条件: 互斥条件:一个资源每次只能被一个进程使用。请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。不剥夺条件:进程已获得的资源,在末使用完之前,不能强

我自倾怀,君且随意 867

JUC

JAVA多线程基础学习一:基础知识 JAVA多线程基础学习二:synchronized JAVA多线程基础学习三:volatile关键字 JAVA多线程提高一:传统线程技术&amp;传统定时器Timer JAVA多线程提高二:传统线程的互斥与同步&amp;传统线程通信机制 JAVA多线程提高三:线程范围内共享变量&amp;ThreadLocal...

qq_31758759的博客 308

Java面试题总结 - Java多线程篇(附答案)

一、线程的run()和start()有什么区别? 每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,run()方法称为线程体。通过调用Thread类的start()方法来启动一个线程。 start() 方法用于启动线程,run() 方法用于执行线程的运行时代码。run() 可以重复调用,而 start() 只能调用一次。 start()方法来启动一个线程,真正实现了多线程运行。调用start()方法无需等待run方法体代码执行完毕,可以直接继续执行其他的代码; 此时线程..

学Java,找哪吒 3万+

JUC初级篇学习笔记

在Java中,线程部分是一个重点,本篇文章说的JUC也是关于线程的。JUC是java.util.concurrent也就是java并发编程包中的实用的工具类,这个工具类在企业开发中占据着举足轻重的地位。native关键字,java代码就无能为力了,其部分就是操作系统完成,最终也就是由操作系统决定的,至于什么时候创建由操作系统决定。十五、JUC-集合线程安全-ArrayList线程不安全和解决方案(一)我现在打开一个进程,一个进程中会有很多的线程,多线程在一个进程中进行。

xizheng2018的博客 508

面试(03)————多线程

因此,并发关注的是多个任务的启动、执行和完成的顺序,使得多个任务看似在“同时”执行,实际上从宏观角度是的,但从微观角度看,这些任务可能并没有在同一时刻被处理。值得注意的是,在AQS的实现中,一旦线程进入排队队列,即使是非公平锁,线程也需要乖乖排队(新的线程与队列中的线程共同来抢资源,是非公平锁)一个当前内存值V、旧的预期值A、即将更新的值B,当且仅当旧的预期值A和内存值V相同时,将内存值修改为B并返回ture,否则什么都不做,并返回false。QS内部维护了一个先进先出的双向队列,队列中存储的排队的线程。

m0_73376570的博客 1225

【JAVA】java常见面试题——持续更新

SpirngBoot自动配置就是不需要我们写代码,所有的配置都由SpringBoot自动完成。我们一般是通过这个注解来开启自动配置的,通过对包下的这个文件进行扫描,这个文件中包含了可以自动装配的类,当满足@Condition注解指定的条件时,便在依赖的支持下进行实例化注册到Spring容器中。SpringBoot最大特点就是他去除了各种xml配置文件改为application.yml进行统一的配置,并且按照阶梯的模式,简单明了,要使用的对象,则采取注解模式注入,省去大量代码。

别倒在黎明之前的博客 293
上一篇: 开发避坑指南(35):mybaits if标签test条件判断等号=解析异常解决方案
下一篇: 开发避坑指南(36):Java字符串Base64编码实战指南
帧栈
博客等级 码龄2年 335粉丝 120原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

帧栈

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值