ThreadLocal共享线程局部变量和线程同步机制的区别

ThreadLocal是解决线程安全问题一个很好的思路,它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题。在很多情况下,ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,更方便,且结果程序拥有更高的并发性。

对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。

ThreadLocal并不能替代同步机制,两者面向的问题领域不同。

1:同步机制是为了同步多个线程对相同资源的并发访问,是为了多个线程之间进行通信的有效方式;

2:而threadLocal是隔离多个线程的数据共享,从根本上就不在多个线程之间共享变量,这样当然不需要对多个线程进行同步了。

import java.util.Random;

public class ThreadSocpeShareData {
	static ThreadLocal<Integer> t = new ThreadLocal<Integer>();
     public static void main(String[] args) {
    	 for(int i=0;i<3;i++){
    		 new Thread(new Runnable() {

    				@Override
    				public void run() {
    				   int  data = new Random().nextInt();

    		    		System.out.println(Thread.currentThread().getName() +" has put "+ data);
    		    		  t.set(data);
    		    		MyThreadScopeData.getInstance().setName("name" + data);
    		    		MyThreadScopeData.getInstance().setAge("age"+data);
    					new A().get();
    					new B().get();
    				}
    			}).start();
    	 }
	}

     static class A{
    	 public void get(){
    		 int  data = t.get();
    		 MyThreadScopeData myData = MyThreadScopeData.getInstance();
    		 System.out.println("A " + Thread.currentThread().getName() +" "+ data + myData.getAge() + myData.getName()   /*ms.getName()*/);
    	 }
     }
     static class B{
    	 public void get(){
    		 int  data = t.get();
    		 System.out.println("B " + Thread.currentThread().getName()+ " "+ data);
    	 }
     }
}

class MyThreadScopeData{

	private MyThreadScopeData(){}
	private static ThreadLocal<MyThreadScopeData> map = new ThreadLocal<MyThreadScopeData>();
	public static MyThreadScopeData getInstance(){
		MyThreadScopeData instance = map.get();
		if(instance == null){
			instance = new MyThreadScopeData();
			map.set(instance);
		}
		return instance;
	}

	private String name;
	private String age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAge() {
		return age;
	}
	public void setAge(String age) {
		this.age = age;
	}

}

事实上,我们向ThreadLocal中set的变量不是由ThreadLocal来存储的,而是Thread线程对象自身保存。当用户调用ThreadLocal对象的set(Object o)时,该方法则通过Thread.currentThread()获取当前线程,将变量存入Thread中的一个Map内,而Map的Key就是当前的ThreadLocal实例。请看源码,这是最主要的两个函数,能看出ThreadLocal与Thread的调用关系:

public void set(T value) {  
    Thread t = Thread.currentThread();  
    ThreadLocalMap map = getMap(t);  
if (map != null)  
      map.set(this, value);  
else
      createMap(t, value);  
}  
ThreadLocalMap getMap(Thread t) {  
return t.threadLocals;  
} 
  public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); } ThreadLocalMap getMap(Thread t) { return t.threadLocals; }

具体可以看看里面的源码,不过有一点是可以证实的,就是Threadlocal中 创建的线程副本,可以不调用remove来做清理工作,因为jvm在发现线程的调佣不再使用时,会进行自动的垃圾回收操作,我以前写程序在使用Threadlocal时却是经常的进行使用完成之后的清理工作。(防止占用内存,如果创建的副本数量不是太多的话,可以让虚拟机自动来清除)

时间: 2024-07-29 01:06:35

ThreadLocal共享线程局部变量和线程同步机制的区别的相关文章

转载:java 异步机制与同步机制的区别

出自:http://blog.itpub.net/17074730/viewspace-563262/ 所谓异步输入输出机制,是指在进行输入输出处理时,不必等到输入输出处理完毕才返回.所以异步的同义语是非阻塞(None Blocking). 网上有很多网友用很通俗的比喻  把同步和异步讲解的很透彻 转过来 举个例子:普通B/S模式(同步)AJAX技术(异步)                同步:提交请求->等待服务器处理->处理完毕返回   这个期间客户端浏览器不能干任何事          

Java中线程局部变量ThreadLocal使用教程及源码分析

在Java多线程编程中有时候会遇见线程本地局部变量ThreadLocal这个类,下面就来讲讲ThreadLocal的使用及源码分析. ThreadLocal 是Thread Local Varial(线程局部变量)的意思,每个线程在使用线程局部变量的时候都会为使用这个线程局部变量的线程提供一个线程局部变量的副本,使得每个线程都可以完全独立地操作这个线程局部变量,而不会与其他线程发生冲突,从线程的角度来看,每个线程都好像独立地拥有了这个线程局部变量.这样,看似每个线程都在并发访问同一个资源(线程局

线程同步机制(一)--Synchronized,Lock

多个执行线程共享一个资源的情形是最常见的并发编程情景之一.在并发应用中常常遇到这样的情景:多个线程读或者写相同的数据,或者访问相同的文件或者数据库连接.为了防止这些共享资源可能出现错误或者数据不一致,人们引入了临界区(critical section)概念.临界区是一个用以访问共享资源的代码块,这个代码块中同一时间只允许一个线程执行. 为了实现这个临界区,Java提供了同步机制.当一个线程试图访问一个临界区时,它将使用一种同步机制来查看是不是已经有其他线程进入临界区.如果没有,它就进入临界区,如

线程局部变量的使用

共享数据是并发程序最核心的问题之一,对于继承了Thread类或者实现了Runnable接口的对象来说尤其重要.如果创建的对象是实现了Runnable接口的类的实例,用它作为传入参数创建多个线程对象并启动这些线程,那么所有的线程将共享相同的属性.也就是说,如果你在一个线程中改变了一个属性,所有线程都会被这个改变影响. 在某种情况下,这个对象的属性不需要被所有线程共享.Java并发API提供了一个干净的机制,即线程局部变量(Thread-Local Variable),其具有很好的性能. 这里我们将

java 线程之对象的同步和异步

一.多线程环境下的同步与异步 同步:A线程要请求某个资源,但是此资源正在被B线程使用中,因为同步机制存在,A线程请求不到,怎么办,A线程只能等待下去. package com.jalja.org.thread.demo01; public class Thread02 { public synchronized void method1(){ System.out.println("method1:"+Thread.currentThread().getName()); try { T

Java中的闪光点:ThreadLocal是线程Thead的局部变量,可替代同步机制的设计,值得学习和研究

线程局部变量ThreadLocal,是Java支持的一种线程安全机制,目的是解决多线程的并发问题. 具体来讲,就是多个线程访问该实例对象的变量时,该实例对象将其存储为键值对的形式,保证各个线程(键)分别对应一份该变量值(值),从而保证多线程变量值得安全访问. ThreadLocal与同步机制比较 同步机制:用锁机制保证同一时间只有一个线程访问变量(用时间换空间),变量是多线程共享的,设计时要缜密分析什么时候读写?什么时候锁定?什么时候释放? ThreadLocal:提供每个线程一个独立的变量副本

java并发:线程同步机制之ThreadLocal

1.简述ThreadLocal ThreadLocal实例通常作为静态的私有的(private static)字段出现在一个类中,这个类用来关联一个线程.ThreadLocal是一个线程级别的局部变量,下面是线程局部变量(ThreadLocal variables)的关键点: A.当使用ThreadLocal维护变量时,若多个线程访问ThreadLocal实例,ThreadLocal为每个使用该变量的线程提供了一个独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其他线程所对应

浅谈利用同步机制解决Java中的线程安全问题

我们知道大多数程序都不会是单线程程序,单线程程序的功能非常有限,我们假设一下所有的程序都是单线程程序,那么会带来怎样的结果呢?假如淘宝是单线程程序,一直都只能一个一个用户去访问,你要在网上买东西还得等着前面千百万人挑选购买,最后心仪的商品下架或者售空......假如饿了吗是单线程程序,那么一个用户得等前面全国千万个用户点完之后才能进行点餐,那饿了吗就该倒闭了不是吗?以上两个简单的例子,就说明一个程序能进行多线程并发访问的重要性,今天就让我们去了解一下Java中多线程并发访问这个方向吧. **第一

ThreadLocal为什么称作线程局部变量

一.RTFSC java.lang.ThreadLocal<T>的具体实现 那么到底ThreadLocal类是如何实现这种"为每个线程提供不同的变量拷贝"的呢?先来看一下ThreadLocal的set()方法的源码是如何实现的: [java] view plaincopyprint? /** * Sets the current thread's copy of this thread-local variable * to the specified value.  Mo