Java并发编程(七)线程封闭
当访问共享的可变数据时,通常需要使用同步。一种避免使用同步的方式就是不共享数据。
如果仅在单线程内访问数据,就不需要同步。这种技术被称为线程封闭(Thread Confinement),它是实现线程安全最简单的方式之一。当某个对象封闭在一个线程中时,这种用法将自动实现安全性,即使被封闭的对象本身不是线程安全的。
Swing中大量使用线程封闭技术将可视化组件和数据模型封闭到Swing的事件分发线程中实现线程安全性。
另一个常见的例子是JDBC(Java Database Connectivity)的Connection对象。JDBC并没有要求Connection是线程安全的对象。在典型的服务器应用程序中,线程从线程池中获取一个Connection对象,并且用该对象来处理请求,使用完之后再返回给连接池。由于大多数的请求都是由单个线程采用同步的方式来处理,并且在Connection对象返回之前,连接池不会再将它分配给其他线程,相当于隐式地将Connection对象封闭在线程中。
Java并没强制规定某个变量必须由锁保护,也没有强制把某个对象封闭在线程中。线程封闭是在程序设计中的一个考虑因素,必须由程序去实现。
Java语言提供了一些机制来帮助维持线程的封闭性,例如局部变量和ThreadLocal类。
Ad-hoc线程封闭
Ad-hoc线程封闭是指,维护线程封闭性的职责完全由程序来承担。
在volatile变量上存在一种特殊的线程封闭。只要你能确保只有单个线程对共享的volatile变量执行写入操作,那么就可以安全地在这些共享的volatile变量上执行"读取—修改—写入"的操作。这种情况下相当于将修改操作封闭在单个线程中以防止发生竞态条件,并且volatile的可见性还确保其他的线程能看到最新的值。
栈封闭
局部变量的固有属性之一就是封闭在执行的线程中。它们位于执行线程的栈中,其他线程无法访问这个栈。栈封闭不要与核心类库中的ThreadLocal混淆。
栈内的基本数据类型不会被发布出去,但是对象被发布出去了,那么封闭性将被破坏。如果在线程内部使用了非线程安全的对象,那么该对象仍然是线程安全的。
ThreadLocal类
维持线程封闭性一种更规范的方法是使用ThreadLocal,这个类能使线程中的某个值与保存值的对象关联起来。ThreadLocal提供了get与set等访问接口或方法,这些方法为每个使用改变量的线程都存有一份独立的副本,因此get总是返回由当前执行线程在调用set时设置的最新值。
ThreadLocal对象通常用于防止对可变的单实例变量(Singleton)或全局变量进行共享。
在单线程应用程序中可能会维持一个全局的数据库连接,并在程序启动的时候初始化这个连接对象,从而避免在调用每个方法时都要传递一个Connection对象。当多个线程在没有协同的情况下就使用全局变量,就不是线程安全的。通过将JDBC的连接保存到ThreadLocal对象中,每个线程都会拥有属于自己的连接。
如果需要频繁执行的操作需要一个临时的对象,例如一个缓冲区,又希望避免每次执行时重新分配该临时对象,就可以使用这项技术。而不是使用共享的静态缓冲区(这个需要锁机制)。
Java并发编程(七)线程封闭的更多相关文章
- Java并发编程:线程封闭和ThreadLocal详解
转载请标明出处: http://blog.csdn.net/forezp/article/details/77620769 本文出自方志朋的博客 什么是线程封闭 当访问共享变量时,往往需要加锁来保证数 ...
- Java并发编程:线程池的使用
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition
Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...
- Java并发编程:线程池的使用(转)
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- Java并发编程:线程控制
在上一篇文章中(Java并发编程:线程的基本状态)我们介绍了线程状态的 5 种基本状态以及线程的声明周期.这篇文章将深入讲解Java如何对线程进行状态控制,比如:如何将一个线程从一个状态转到另一个状态 ...
- Java 并发编程:线程间的协作(wait/notify/sleep/yield/join)
Java并发编程系列: Java 并发编程:核心理论 Java并发编程:Synchronized及其实现原理 Java并发编程:Synchronized底层优化(轻量级锁.偏向锁) Java 并发编程 ...
- (转)Java并发编程:线程池的使用
背景:线程池在面试时候经常遇到,反复出现的问题就是理解不深入,不能做到游刃有余.所以这篇博客是要深入总结线程池的使用. ThreadPoolExecutor的继承关系 线程池的原理 1.线程池状态(4 ...
- Java并发编程:线程池的使用(转载)
转载自:https://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实 ...
- Java并发编程:线程池的使用(转载)
文章出处:http://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实 ...
- [转]Java并发编程:线程池的使用
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
随机推荐
- Exercise02_03
import java.util.Scanner; public class Mi { public static void main(String[] args){ Scanner input = ...
- 一个强大的UI node 抽象
基于cocos2d -x的一个强大的 界面对象的基类 ---@type uinode ui 对象的抽象 --@usage -- 界面打开的执行流程 -- 带*的是可选重写的函数,不带*的为必须实现的 ...
- Java杂谈6——Java安全模型
Java语言安全模型是其有别于传统的编程语言的一个很重要的特点,采用一种沙箱模型隔离了Java的运行环境与具体的操作系统,使得Java在网络环境下能够更为安全的运行.理解Java的安全模型,能够帮助我 ...
- sqlserver 获取系统用户表结构信息
SELECT (case when a.colorder=1 then d.name else null end) 表名, a.colorder 字段序号,a.name 字段名, (case when ...
- 说一下集成 diagram-viewer 的心路历程 5.22.0
1. 下载部署包文件地址:https://github.com/Activiti/Activiti/releases/download/activiti-5.22.0/activiti-5.22.0. ...
- Shell实现多级菜单系统安装维护脚本实例分享
Shell实现多级菜单系统安装维护脚本实例分享 这篇文章主要介绍了Shell实现多级菜单系统安装维护脚本实例分享,本文脚本用多级菜单实现管理WEB服务器.Mysql服务器.Nginx服器等,需要的朋友 ...
- 计算两个经纬度之间的距离(python算法)
EARTH_REDIUS = 6378.137 def rad(d): return d * pi / 180.0 def getDistance(lat1, lng1, lat2, lng2): r ...
- 多个客户端连接socket
import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import ...
- 安装Scala 找不到或无法加载主类 scala.tools.nsc.MainGenericRunner 错误
对于安装Scala时 找不到或无法加载主类 scala.tools.nsc.MainGenericRunner 错误,不管是linux还是window系统,原因很大可能是scala的安装路径中出现空格 ...
- Android使用tcpdump抓包
AllJoyn中有个问题:Server切换到Client后,重新加入其他Server时join session会失败,原因是timeout(join session是异步的,在指定时间内没有收到回应) ...