Java并发编程五-Java并发机制的底层实现原理-synchronized
参考文献
<<Java并发编程艺术>>
<<Java语言规范-基于Java SE 8>>
http://www.itabin.com/synchronized-lock/
引言
Java编程语言提供了多种用于线程通信的机制.这些方法中最基础的就是同步(synchronization),它是使用监视器(monitor)实现的.Java中每个对象都与一个线程可以锁定或解锁的监视器相关联.在任何时刻,只有一个线程可以持有某个监视器上的锁.任何其他试图锁定该监视器线程都将阻塞,直到它们可以获得该监视器上的锁.
线程T可以多次锁定某个特定的监视器,而每个解锁操作都会抵消一次锁定操作的效果.(可重入锁)
synchronized
synchronized语句是对对象的引用,即基于对象实现,然后它试图执行在该对象的监视器上的锁定动作,并且在锁定动作成功完成之前,不会执行下一步动作.在锁定动作执行之后,synchronized语句体被执行.如果该语句体执行结束,无论是正常结束还是异常结束,都会在相同的监视器上执行解锁动作.
syn ...
Java并发编程(四)-Java并发机制的底层实现原理-volatile
参考文献
<<Java并发编程艺术>>
<<Java语言规范-基于Java SE 8>>
CPU高速缓存行与内存关系 及并发MESI 协议
[死磕 Java 并发] — Java内存模型之分析volatile
volatile
CPU术语
术语
英文
描述
内存屏障
memory barrier
是一组处理器指令,用于实现对内存操作的顺序限制
缓存行
cache line
缓存中可以分配的最小存储单位.处理器填写缓存行时会加载整个缓存行,需要使用多个主内存读周期
原子操作
atomic operations
不可中断的一个或一系列操作
缓存行填充
cache line fill
当处理器识别到从内存中读取操作数是可缓存的,处理器读取整个缓存行到适当的缓存(L1,L2,L3的或所有)
缓存命中
cache hit
如果进行高速缓存行填充操作的内存位置仍然是下次处理器访问的地址时,处理器从缓存中读取操作数,而不是内存读取
写命中
write hit
当处理器将操作数写回到一个内存缓存的区域时,它首先会检 ...
Java并发编程(三)-锁
参考文献
锁的简单应用
图解Java中那18 把锁
<<Java并发编程艺术>>
Synchronization
锁
锁的分类
分类标准把锁分为以下 7 大类别
偏向锁/轻量级锁/重量级锁;
可重入锁/非可重入锁;
共享锁/独占锁;
公平锁/非公平锁;
悲观锁/乐观锁;
自旋锁/非自旋锁;
可中断锁/不可中断锁.
使用锁的目的
锁是用来控制多个线程访问共享资源的方式.一个锁能够防止多个线程同时访问共享资源.
死锁
产生死锁的原因
当前线程拥有其他线程需要的资源,当前线程等待其他线程已拥有的资源,同时不放弃自己拥有的资源;
如何预防死锁
只有以下这四个条件都发生时才会出现死锁:
互斥:共享资源X和Y只能被一个线程占用;
占有且等待: 线程T1已取得共享资源X,在等待共享资源Y的时候,不释放共享资源X;
不可抢占: 其他线程不能强行抢占线程T1占有的资源;
循环等待: 线程T1等待线程T2占有的资源,线程T2等待线程T1占有的资源,就是循环等待.
即破坏其中一个,就可以成功避免死锁的发生
对于"占用且等待"这个条件 ...
Java并发编程(二)-线程
参考文献
<<Java并发编程艺术>>
<<深入理解Java虚拟机-JVM高级特性与最佳实践>>
线程
线程的创建和运行
直接使用Thread
1Thread t= new Thread(()->{}).start();
Runnable配合Thread
123Runnable runnable = () -> log.debug("hellow");Thread t = new Thread(runnable);t.start;
实现Callable接口通过FutureTask包装器来创建Thread线程;
12345678// FutureTask能接收Callable类型的参数,用来处理返回结果FutureTask<String> task = new FutureTask<>(()->{ log.debug("hello"); return "demo";})new Thr ...
Java并发编程(一)-并发相关知识点
参考文献
并发与并行的区别是什么?
<<Java并发编程实战>>
极客时间:Java并发编程实战
必懂系列!Java并发面试题
【对线面试官】多线程基础
<<Java并发编程艺术>>
Java 并发 - 理论基础
ON JAVA 进阶卷
进程之间通信的方式
RPC/HTTP/信号量/消息队列/管道/socket
并发编程中核心的问题
分工: 如何高效地拆解任务并分配给线程
Java SDK Fork/Join框架就是一种分工模式
同步: 指线程之间如何协作
CountDownLatch就是一种典型的同步方式
互斥: 保证同一时刻只允许一个线程访问共享资源
可重入锁则是一种互斥手段
同步
并发编程领域的同步主要指线程之间的协作,指一个线程执行完了一个任务,如何通知后续任务的线程开工
工作中遇到的线程协作问题,基本上都可以描述为这样一个问题:
当某个条件不满足时,线程需要等待;
当某个条件满足时,线程需要被唤醒执行;
解决协作问题的核心技术是"管程"
互斥
实现互斥的核心技术是锁 ...
工具-JMH官方示例(一)
参考文献
Simples
官方样例(1~12)
Hello World
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104/* * Copyright (c) 2014, Oracle America, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code mu ...
工具-JMH官方示例(二)
参考文献
Simples
官方样例(13~end)
RunToRun
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129/* * Copyright (c) 2014, Oracle America, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that ...
JDK8特性-Stream流式操作
参考文献
Java8 实战
Stream API
只能对实现了java.util.Collection接口的类做流操作.
流(Stream)是数据渠道,用于操作数据源(集合,数组等)所生成的元素序列.
集合讲的是数据,流讲的是计算
Stream自己不会存储元素
Stream不会改变源对象.相反,它们会返回一个持有结果的新Stream.
Stream操作是延迟执行的,这意味着它们等到需要的时候才执行.
Stream支持同步执行,也支持异步执行.
惰性流
流是惰性的,在达到终止条件前不会处理元素,达到终止条件后逐个处理每个元素.如果遇到短路操作,那么只要满足所有条件,流处理就会终止.
对于集合而言,必须执行完所有操作才能进行下一步操作.对于流而言,各种中间操作构成一条流水线,但在流达到终止操作前不会处理任何元素,达到终止操作后只处理所需的值.
流处理并非任何情况下都有意义:如果进行任何状态操作(如排序或求和),就不得不处理所有值.但是如果无状态操作后跟一个短路终止操作,流处理的优点还是很明显的.
注意点
请注意,和迭代器类似,流只能遍历一次
12345678910publ ...
JDK8特性-lambda表达式
参考文献
Java攻略:Java常见问题的简单解法
Java8 实战
lambda表达式
函数式接口:是一种包含单一抽象方法(single abstract method)的接口.类通过为接口中的所有方法提供实现来实现任何接口,这可以通过顶级类(top-level class),内部类甚至匿名内部类完成.
lambda表达式必须匹配接口中单一方法签名的参数类型和返回类型,这被称为与方法签名兼容.因此lambda表达式属于接口方法的实现,可以将其赋值给该接口类型的引用.
Java库中不存在名为lambda的类,lambda表达式只能被赋值给函数式接口引用.
lambda表达式在任何情况下都不能脱离上下文存在,上下文指定了将表达式给哪个函数式接口.
lambda表达式既可以是方法的参数,也可以是方法的返回类型,还可以被赋给引用.
无论哪种情况,赋值类型必须为函数式接口.
lambda表达式的本质就是匿名函数,在定义和调用时不需要被赋予类型名或绑定到标识符.
方法引用
使用**双冒号表示法(::)**将示例引用或类名与方法分开.
语法
object: ...
Java基础-数据库配置
参考文献
JDBC连接数据库的流程
在开发环境中加载指定数据库的驱动程序
在Java程序中加载程序
1ClassName.forName("com.mysql.cj.jdbc.Driver");
创建数据连接对象
12// URL = 协议名 + IP地址 + 端口 + 数据库名称Connection connection = DriverManager.getConnection("连接数据库的URL","用户名","密码");
创建Statement对象
1Statement statement = connection.createStatement();
调用Statement对象的相关方法执行对应的SQL
1ResultSet resulte = statement.excuteUpdate("SQL");
关闭数据库连接
1connection.close();
各种数据库URL配置
1234567891011121314mysql:jdbc:my ...