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并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
随机推荐
- (转)MOMO的Unity3D研究院之深入理解Unity脚本的执行顺序(六十二)
http://www.xuanyusong.com/archives/2378 Unity是不支持多线程的,也就是说我们必须要在主线程中操作它,可是Unity可以同时创建很多脚本,并且可以分别绑定在不 ...
- Kingdee Apusic 中间件有关资料
Kingdee Apusic 中间件有关资料: 1.官方网站:http://www.apusic.com 2.资料目录:http://www.apusic.com/dist 3.Apusic 8 资料 ...
- ylbtech-LanguageSamples-ConditionalMethods(条件方法)
ylbtech-Microsoft-CSharpSamples:ylbtech-LanguageSamples-ConditionalMethods(条件方法) 1.A,示例(Sample) 返回顶部 ...
- 各种分布 高斯 Gamma Beta 多项分布
- linux systemctl service examples
一.脚本服务化目的 1.python 在 文本处理中有着广泛的应用,为了满足文本数据的获取,会每天运行一些爬虫抓取数据.但是网上买的服务器会不定时进行维护,服务器会被重启.这样我们的爬虫服务就无法运行 ...
- jQuery:多个AJAX/JSON请求相应单个回调
原文链接:jQuery: Multiple AJAX and JSON Requests, One Callback 原文日期: 2014年4月15日 翻译日期: 2014年4月22日 翻译人员: 铁 ...
- TestNG+Jenkins+Maven参数化测试dubbo接口
1.TestNG参数化测试用例: package com.tree.autotest.testcase.IUserBankSummaryService; import com.datatrees.fi ...
- vue - 认识ora
主要用来实现node.js命令行环境的loading效果,和显示各种状态的图标等... const ora = require('ora'); const spinner = ora('Loading ...
- 微信小程序 - 回到自己位置(map)
演示效果: 图片资源 index.js /** * 回到自己位置,在cover-image上绑定点击事件即可. */ clickcontrol(e) { let mpCtx = wx.createMa ...
- 去除前后空格,Oracle和SQLSERVER都适用。ltrim(rtrim(’ ‘))
Oracle自带去除方法:trim(). 但是sql语法中没有直接去除两头空格的函数,但有ltrim()去除左空格rtrim()去除右空格. 合起来用就是sql的trim()函数,即select lt ...