ThreadLocal 和Synchronized
并发都用到, 两个都是解决了线程并发问题,区别呢?
Synchronized 同步机制, 共有变量被多个线程使用,会出现线程不安全,所以,加锁,锁机制很多种,例如Synchronized, lock 锁, 阻塞队列。以时间换空间, 某一个线程拿到锁, 先进去, 其他线程, 等着吧~
ThreadLocal ,当多个线程使用一个对象, 以空间换时间, 创建不同的变量副本。大家不要抢, 每个人都有!首先这个对象是全局变量。
ThreadLocal 保证了线程的隔离性 ,一个经典的例子是 SimpleDateFormat 线程不安全问题, 这个时间格式化 工具类我们使用频率非常大 。
Synchronized使用场景:比如1000 张火车票, 每个线程操作, 必须保证每个窗口卖 不同 的火车票, 保证座位不相同! 这1000 张票是原子性的。
ThreadLocal使用场景:举例: spring security管理权限 , 每个用户用户名,密码验证登录会存在 Authentication中, 包括用户名密码, 是否被锁定, 是否过期,等很多消息, 这是一个对象, 当用户登录之后, 使用这个系统, 比如查看自己的订单,自己的购物车,自己的余额 ,这里Authentication 就是全局变量,如果多个用户登录,这个对象肯定会被改变, 简单的方法是 每一个用户 授权登录后, 都生成一个全局变量对象, 但是1000 万 个用户呢,系统会不会垮掉?肯定是!
这就是线程并发非同步的另一种领域,数据隔离,保证每个用户有各自的数据, 用同步加锁是不能解决的。
所以可以创建一个threadLocal , 看看 spring security 的源码:
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package org.springframework.security.core.context; import org.springframework.util.Assert; /**
* A <code>ThreadLocal</code>-based implementation of
* {@link SecurityContextHolderStrategy}.
*
* @author Ben Alex
*
* @see java.lang.ThreadLocal
* @see org.springframework.security.core.context.web.SecurityContextPersistenceFilter
*/
final class ThreadLocalSecurityContextHolderStrategy implements
SecurityContextHolderStrategy {
// ~ Static fields/initializers
// =====================================================================================
//核心在这里 , 这里创建 一个 threadLocal 的 SecurityContext
private static final ThreadLocal<SecurityContext> contextHolder = new ThreadLocal<SecurityContext>(); // ~ Methods
// ======================================================================================================== public void clearContext() {
contextHolder.remove();
} public SecurityContext getContext() {
SecurityContext ctx = contextHolder.get(); if (ctx == null) {
ctx = createEmptyContext();
contextHolder.set(ctx);
} return ctx;
} public void setContext(SecurityContext context) {
Assert.notNull(context, "Only non-null SecurityContext instances are permitted");
contextHolder.set(context);
} public SecurityContext createEmptyContext() {
return new SecurityContextImpl();
}
}
再看看线程全局变量怎么被设置进去
//这个是登录方法, 用户名密码登录
public void login(String username, String password) throws ServletException {
if (isAuthenticated()) {
throw new ServletException("Cannot perform login for '" + username
+ "' already authenticated as '" + getRemoteUser() + "'");
}
AuthenticationManager authManager = authenticationManager;
if (authManager == null) {
logger.debug("authenticationManager is null, so allowing original HttpServletRequest to handle login");
super.login(username, password);
return;
}
Authentication authentication;
try {
//这里去数据库验证, 用户名错误?用户名过期?用户被锁定?用户什么角色
authentication = authManager
.authenticate(new UsernamePasswordAuthenticationToken(username,
password));
}
catch (AuthenticationException loginFailed) {
SecurityContextHolder.clearContext();
throw new ServletException(loginFailed.getMessage(), loginFailed);
}
//这里全是全局变量 设置进去
SecurityContextHolder.getContext().setAuthentication(authentication);
}
好了, 一个验证通过了, 并被设置到threadLocal ,
现在用户删除订单
@RequestMapping(value = "/deleteId", method = RequestMethod.POST)
@ResponseBody
public JSONObject deleteId(@RequestParam("strJson")String json) {
//SecurityContextHolder 是一个全局变量, 直接在方法里面获取
Authentication auth = SecurityContextHolder.getContext()
.getAuthentication();
Integer role=-1;
Object pinciba = auth.getPrincipal();
if (pinciba instanceof Customer) {
role =((Customer) pinciba).getRole();
} if(role==2){
//管理员删除
}else{
//非管理员不能删除
}
JSONObject jsons = new JSONObject();
System.out.println(json);
return jsons;
}
threadlocal 很强大, 一种弱引用。我们知道Java有四中对象:
从JDK1.2版本开始,把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期。这四种级别由高到低依次为:强引用、软引用、弱引用和虚引用。
threadLocal 就是一种弱引用, 当某个用户很长时间没有登录, 而 其他用户需要threadLocal 添加一个自己的 变量, 就会回收没有使用了, 实现了线程数据隔离吧。
ThreadLocal 和Synchronized的更多相关文章
- 【转】Java多线程编程中易混淆的3个关键字( volatile、ThreadLocal、synchronized)总结
概述 最近在看<ThinKing In Java>,看到多线程章节时觉得有一些概念比较容易混淆有必要总结一下,虽然都不是新的东西,不过还是蛮重要,很基本的,在开发或阅读源码中经常会遇到,在 ...
- 并发与同步 (一) ThreadLocal与Synchronized 用哪一个好
ThreadLocal是什么? 历史 早在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路.使用这个工具类可以 ...
- 处理java多线程时线程安全问题 - ThreadLocal和Synchronized
多线程在自动化测试中用的不多,也就是说我们用单线程可以完成大部分的自动化测试脚本. 主要有两个原因,首先是因为自动化测试首要考虑的是脚本的稳定性,所以一般会牺牲效率以保证脚本稳定,其次是由于局限于我们 ...
- 多线程学习三:Thread API,ThreadLocal,synchronized,volatile和Condition
一.Thread API: setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) 首先要了解什么是Thread. ...
- ThreadLocal与Synchronized区别
ThreadLocal和Synchonized都用于解决多线程并发访问他们两者的区别:synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问,而ThreadLocal为每一 ...
- ThreadLocal 与 Synchronized区别
相同:ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题.不同:Synchronized同步机制采用了“以时间换空间”的方式,仅提供一份变量,让不同的线程排队访问:而Thr ...
- ThreadLocal与Synchronized
package com.demo; import org.hibernate.HibernateException; import org.hibernate.classic.Session; imp ...
- ThreadLocal, volatile, synchronized, map, epoll, AQS简单总结
ThreadLocal ThreadLocal主要是为了解决内存泄漏的问题,它是一种弱引用: 引用总共有四种,,我简单列一下: 强引用(Strong Reference):正常引用,根据垃圾回收算法, ...
- synchronized + volatile + ThreadLocal
线程的共享 synchronized + volatile + ThreadLocal <1> synchronized 锁住的是对象,当用它来锁住一个类时,实际上也是锁的一个对象. ...
随机推荐
- FusionCharts xml入门教程
由于项目需求需要做一个报表,选择FusionCharts作为工具使用.由于以 前没有接触过报表,网上也没有比较详细的fusionCharts教程,所以决定好好研究FusionCharts,同时做一个比 ...
- C# 在SQLite数据库中存储图像 z
C# 在SQLite数据库中存储图像 更多 0 C# SQLite 建表语句 CREATE TABLE [ImageStore]([ImageStore_Id] INTEGER NOT NULL ...
- 在ubuntu12.0.4上搭建samba服务器以实现文件共享
在安装之前samba服务器之前,先进行以下配置和测试. <壹> 准备工作 一.NAT联网方式 (1)硬件连接 无需网线,无需路由器 (2)虚拟机选择NAT连接方式 (3)测试网络通不通 在 ...
- swift 语法 - 以及学习资料
附上一些swift的一下学习资料: 1.Swift语法介绍官方英文版:The Swift Programming Language 2.Swift与Objective-C相互调用Using Swift ...
- A simple test
博士生课程报告 视觉信息检索技术 博 士 生:施 智 平 指导老师:史忠植 研究员 中国科学院计算技术研究所 2005年1月 目 ...
- bzoj 3597: [Scoi2014]方伯伯运椰子 0/1分数规划
3597: [Scoi2014]方伯伯运椰子 Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 144 Solved: 78[Submit][Status ...
- Json字符串转换为java对象的各种实现方法【json_lib框架、Gson、org.json】
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://mengzhengbin520.blog.51cto.com/7590564/12 ...
- 【2011 Greater New York Regional 】Problem H: Maximum in the Cycle of 1
也是一个数学题: 主要用到的是排列组合的知识,推推公式就行了,挺简单的: 唯一要注意的是A(0,0)=1: 在这个上面WA了几次,= = 代码: #include<stdio.h> #de ...
- 最新ps cs6序列号 永久免费可用
一. 序列号 除非是从官方购买,从其它任何途径得到的序列号(包括网上流传的注册机生成的)都是不能通过联网验证的,必须使用破解补丁,或是通过修改hosts文件的方式来激活.因此,除了正版,不存在所谓的“ ...
- CSS实现Div透明,而显示在上面的文字不透明,但也可看到显示在下面的图片内容
CSS实现Div透明,而显示在上面的文字不透明,但也可看到显示在下面的图片内容,DiV透明其实挺简单,主要是为background定义opacity属性,一般这个是最大值是1,数值越接近1,则越不透明 ...