线程安全的代码本质上是管理队状态的访问,而且是共享/可变的状态.
一个对象的状态就是它的数据,存在状态变量中,还包括了任何会对它外部可见行为产生影响的数据.
共享:一个变量被对个线程访问
可变:变量的值会在其生命周期内可以改变
线程安全性的实质是在不可控制的并发访问中保护数据
一个对象是否应该是线程安全的取决于它是否会被多个线程访问.
线程安全的性质取决于程序中如何使用对象,而非对象完成了什么
保证对象的线程安全性需要使用同步来协调对其可变状态的服务.
若多余一个线程访问某个变量,某线程还会修改其值,则必须使用同步机制来协调线程对变量的访问.
Java同步机制synchronized提供独占锁,还有volatile变量、显示锁、原子变量使用等。
设计线程安全的类时,优秀的面向对象技术——封装、不可变性及明确的不变约束会提供很多帮助。
线程安全性——一个类是线程安全的,是指在很多个线程访问时,类可以持续进行正确的行为。
线程安全的类封装了任何必要的同步,因此客户端无需自己提供。
对线程安全类的实例进行顺序或并发的一系列操作都不会导致实例处于无效状态。
无状态的线程永远是线程安全的——>多数的Servlet都是无状态的
多线程中的竞争条件——当计算的正确性依赖于运行时中相关的时序或多线程的交替时会产生竞争条件。
最常见的竞争条件是——检查再运行(check_and_act)
常见用法:惰性初始化——延迟对象的初始化,直至程序真正使用它,且只初始化一次。(单例模式)
复合操作:为了保持线程安全性,操作必须原子的操作(自增操作不慎原子操作——读——改——写)
因此引入了锁机制(Java内置的原子性机制)
Java.util.concurrent.atomic包中包括了原子变量类,这些类用来实现数字和对象引用的原子状态的转换。但这些类只能添加一个状态变量,当多个状态变量时,需要用锁机制。
锁:Java提供了强制原子性的内置锁机制:synchronized块:分2部分,即:锁对象的引用+锁保护的代码块,形如:
Synchronized(lock){}
每个Java对象都可以隐式是一个用于同步的锁,这些内置的锁叫做“内部锁/监视器锁”。
执行线程进入synchronized块前会自动获得锁,无论通过正常退出还是抛出异常,线程都会在放弃对synchronized块的控制时自动释放锁。
获得锁的唯一方法:进入这个内部锁保护的同步块或方法。
内部锁在Java中是一个互斥锁,至多有一个线程可以拥有锁。
同一时间,只能有一个线程可以运行特定锁保护的代码块,因此,由用一个锁保护的synchronized块会各自原子的执行,不会相互干扰。
重进入:当一个线程请求其他线程正占有的锁时,请求线程会被阻塞;但内部锁是可重进入的。因此线程在试图获得她自己占有的锁时,请求会成功。
重进入意味着请求是基于“每线程”的,而非“每调用”的。
重进入的实现是通过为每个锁关联一个请求计数+一个占有它的线程。当计数=0时,表示锁未被占有;当线程请求一个未被占有的锁时,JVM记录锁的占有者,并把请求计数置为1;如果同一个线程再次请求这个锁,则计数+1;如果每次占用线程退出同步块,计数-1,直至计数=0,锁才释放。
如果没有重进入,子类同名同步方法调用父类同名同步方法会死锁。
锁用来保护状态:
仅仅用Synchronized块包装复合操作是不够的,如果用同步来协调访问变量,每次访问变量都要同步。用锁来协调访问变量时,每次访问变量都需要同一个锁。
对象的内部锁与他的状态之间没有内在的关系
即使获得了与对象关联锁也不能阻止其他线程访问这个对象——获得了对象的锁,唯一可做的事情是阻止其他线程再获得相同的锁。
常见的锁规则是在对象内部封装所有的可变状态。通过对象的内部锁来同步任何访问可变状态的代码路径,保护他在并发访问中的安全。
共享对象
Synchronized作用:原子操作或划定“临界区”+内存可见性
因此,我们不仅希望避免当一个线程修改其他线程正在使用的对象的状态,还希望当一个线程修改了对象状态后,其他线程能看到变化。
为了保证跨线程写入的内存可见性,必须使用同步机制(只要数据需要被跨线程共享,就进行恰当的同步)
当访问一个共享的可变变量时,为什么需要所有的线程由同一个锁同步?为了保证一个线程对数据的写入,其他线程都可见。
因此说,锁不仅仅关于同步于互斥,也关于内存可见性。
Volatile变量
弱同步方式:Volatile变量:确保对一个变量的更新以可预见的方式告知其他线程。
当一个域声明为Volatile类型后,编译器与运行时会监事这个变量,他是共享的,且对他的操作不会与其他的内存操作一起被重排序。
Volatile变量不会缓存在寄存器或缓存在对其他处理器隐藏的地方。
读取一个Volatile变量的操作不会加锁,不会引起执行线程的阻塞————是一种轻量级同步机制。
因此:加锁可以保证可见性与原子性;但Volatile变量只能保证可见性。
使用Volatile变量的标准:
写入变量时并不依赖变量的当前值,或者能确保只有单一的线程修改变量的值;
变量不需要与其他的状态变量共同参与不变约束;
访问变量时,没有其他的原因需要加锁
发布和逸出
发布一个对象的意思是它能被当前范围之外的代码使用;
一个对象在尚未准备好时就发布——逸出
线程封闭:不共享数据,如应用池化的JDBC的Connection对象
Ad-hoc线程限制
指的是维护线程限制性的任务全部落在实现上—容易出错
栈限制
线程限制的一种,在栈限制中,只能通过本地变量才能触及对象
ThreadLocal
允许你将每个线程与持有数值的对象关联在一起,并提供了get/set访问器。为每个使用它的线程维护一份单独的拷贝。因此get总是返回当前线程通过set设置最新的值。
不可变性:为了满足同步的需要,另一种方法是使用不可变对象。
相关推荐
这本"Java并发编程学习笔记"可能是作者在深入研究Java并发特性、工具和最佳实践过程中积累的心得体会。下面,我们将根据这个主题,探讨一些关键的Java并发编程知识点。 1. **线程与进程**:在多任务环境中,线程是...
Java并发编程是Java开发中必不可少的一部分,涉及到多线程、同步机制、线程池以及并发工具类等多个核心知识点。以下是对这些主题的详细说明: 1. **线程安全与锁 Synchronized 底层实现原理**: 线程安全是指在多...
Java并发编程学习笔记,研究JAVA并发多线程编程的一本教程,使用并发技术可以开发出并行算法,充分利用多处理器的计算能力,避免硬件资源浪费。目前,在JAVA并发编程方面的论述系统且内容详实的技术资料不太多,Java...
### Java并发编程实践笔记知识点详解 #### 一、保证线程安全的方法 1. **不要跨线程访问共享变量:** 当多个线程共享某个变量时,若其中一个线程修改了该变量,其他线程若没有正确同步,则可能读取到错误的数据。...
### Java并发编程学习笔记知识点详解 #### 一、Java并发编程概述 Java并发编程是指在Java应用程序中同时执行多个操作的技术。它通过多线程、线程池等机制实现资源的有效利用,提高程序运行效率。Java并发编程的...
Java并发编程是Java开发中的重要领域,它涉及到多线程、同步、锁机制、线程池等关键概念,是提高程序性能和效率的关键技术。在Java中,并发编程的运用可以充分利用多核处理器的能力,实现高效的多任务处理。以下是对...
Java并发编程系列心得笔记,可以参考,欢迎共同交流学习
本文将基于文档《Java并发编程与高并发解决方案-学习笔记***.pdf》中提供的内容,来详细阐述并发编程和高并发的基本概念、CPU多级缓存与缓存一致性、以及Java内存模型。 ### 并发与高并发概念 在现代多线程编程中...
Java并发编程 背景介绍 并发历史 必要性 进程 资源分配的最小单位 线程 CPU调度的最小单位 线程的优势 (1)如果设计正确,多线程程序可以通过提高处理器资源的利用率来提升系统吞吐率 ...
Java并发编程与高并发解决方案是开发高性能应用的关键技术。在基础篇中,主要涉及以下几个重要知识点: 1. **并发编程基础** - **并发**:并发是指在一个时间段内,多个线程交替执行,使得系统看起来像是同时处理...
Java并发编程 学习资料
java并发编程与并发解决方案是自己多年开发和学习的笔记,有助于(ˇˍˇ) 想~进一步提高的java开发工程师或架构师深入的学习java架构并发处理。同时,它也是 在实际工作中多年高并发解决方案和经验的总结
自己总结的java并发编程的笔记,绘制了详细的思维导图,每个思维导图中均有详细的博文解释,方便大家学习和理解,免费分享给大家。
### Java并发编程与高并发解决方案知识点总结 #### 一、并发与高并发基本概念 ##### 1.1 并发 - **定义**: 指一个程序在同一时刻拥有两个或更多的线程,这些线程可以在单核或多核处理器上运行。 - **单核处理器上...
"JUC并发编程学习笔记(硅谷)"很可能包含了关于Java并发工具集(Java Util Concurrency, JUC)的深入理解和实战经验。JUC是Java标准库提供的一套强大的并发处理工具,它极大地简化了多线程编程,提高了程序的可读性...
《Java并发编程之美》学习笔记 《Java concurrency programming》learning note
学习Java并发编程时,锁的概念是无法回避的。锁是同步的一种机制,用来控制多个线程访问共享资源的顺序。在Java中,锁主要有两种类型:内置锁和显示锁。内置锁使用synchronized关键字实现,而显示锁则是通过java....
Java并发库是Java平台中的核心组件,它为多线程编程提供了丰富的工具和接口,使得开发者能够高效、安全地实现并发程序。在Java并发库中,ExecutorService接口和相关的线程池是其核心部分,它们提供了线程管理和任务...
本学习笔记主要涵盖了Java的基础知识,包括面向对象、集合、IO流、多线程、反射与动态代理以及Java 8的新特性等方面,旨在帮助初学者或有经验的开发者巩固和提升Java编程技能。 1. 面向对象(OOP):Java的核心是...