前言
在学习sychronized
关键字及其实现细节的时候,发现java中的三种锁,偏向锁,轻量级锁,重量级锁,引入偏向锁是为了在无多线程竞争的情况下尽量减少不必要的轻量级锁执行路径,因为轻量级锁的获取及释放依赖多次CAS
原子指令,而偏向锁只需要在置换ThreadID
的时候依赖一次CAS
原子指令,代价就是一旦出现多线程竞争的情况就必须撤销偏向锁。
AQS(AbstractQueuedSynchronizer)是一个用于构建锁和同步器的框架,许多同步器都可以通过AQS很容易并且高效的构造出来。不仅Reentrant和Semaphore是基于AQS构建的,还包括CountDownLatch、ReentrantReadWriteLock、SynchronousQueue和FutureTask。
为了换取性能,JVM在内置锁上做了非常多的优化,膨胀式的锁分配策略就是其一。理解偏向锁、轻量级锁、重量级锁的要解决的基本问题,几种锁的分配和膨胀过程,有助于编写并优化基于锁的并发程序。
为何要使用Java线程同步? Java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时,将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用,从而保证了该变量的唯一性和准确性。
但其并发编程的根本,就是使线程间进行正确的通信。其中两个比较重要的关键点,如下:
- 线程通信:重点关注线程同步的几种方式;
- 正确通信:重点关注是否有线程安全问题;
Java中提供了很多线程同步操作,比如:synchronized关键字、wait/notifyAll、ReentrantLock、Condition、一些并发包下的工具类、Semaphore,ThreadLocal、AbstractQueuedSynchronizer等。本文主要说明一下这几种同步方式的使用及优劣。
在过去单CPU时代,单任务在一个时间点只能执行单一程序。之后发展到多任务阶段,计算机能在同一时间点并行执行多任务或多进程。虽然并不是真正意义上的“同一时间点”,而是 多个任务或进程共享一个CPU,并交由操作系统来完成多任务间对CPU的运行切换,以使得每个任务都有机会获得一定的时间片运行。
再后来发展到多线程技术,使得在一个程序内部能拥有多个线程并行执行。一个线程的执行可以被认为是一个CPU在执行该程序。当一个程序运行在多线程下,就好像有多个CPU在同时执行该程序。
多线程比多任务更加有挑战。多线程是在同一个程序内部并行执行,因此会对相同的内存空间进行并发读写操作。这可能是在单线程程序中从来不会遇到的问题。其中的一些错误也未必会在单CPU机器上出现,因为两个线程从来不会得到真正的并行执行。然而,更现代的计算机伴随着多核CPU的出现,也就意味着 不同的线程能被不同的CPU核得到真正意义的并行执行。
所以,在多线程、多任务情况下,线程上下文切换是必须的,然而对于CPU架构设计中的概念,应先熟悉了解,这样会有助于理解线程上下文切换原理。
MySQL是现在最流行的关系型数据库(RDB)的选择, 创建一个应用时,无论是用户数据还是订单数据,使用关系型数据库存储是最可靠稳定的选择,借助RDB提供的可靠性、事务等功能,为应用提供完善的支持。MySQL是开源软件,可以免费使用,MySQL在发展多年后越来越成熟,成为大部分公司的数据库首选。MySQL采用插件式的存储引擎架构,5.5版本后默认使用InnoDB存储引擎。
MySQL从概念上可以分为四层,顶层是接入层,不同语言的客户端通过mysql的协议与mysql服务器进行连接通信,接入层进行权限验证、连接池管理、线程管理等。下面是mysql服务层,包括sql解析器、sql优化器、数据缓冲、缓存等。再下面是mysql中的存储引擎层,mysql中存储引擎是基于表的。最后是系统文件层,保存数据、索引、日志等。