ThreadLocal与synchronized多线程并发访问区别2【转】
2009-11-27 14:26
501 查看
ThreadLocal与synchronized多线程并发访问区别2【转】
2009-11-0411:50
2009-11-0411:50
ThreadLocal 由上面可以知道,使用同步是非常复杂的。并且同步会带来性能的降低。Java提供了另外的一种方式,通过ThreadLocal可以很容易的编写多线程程序。从字面上理解,很容易会把ThreadLocal误解为一个线程的本地变量。其它ThreadLocal并不是代表当前线程,ThreadLocal其实是采用哈希表的方式来为每个线程都提供一个变量的副本。从而保证各个线程间数据安全。每个线程的数据不会被另外线程访问和破坏。 我们把第一个例子用ThreadLocal来实现,但是我们需要些许改变。 Student并不是一个私有变量了,而是需要封装在一个ThreadLocal对象中去。调用ThreadLocal的set方法,ThreadLocal会为每一个线程都保持一份Student变量的副本。所以对student的读取操作都是通过ThreadLocal来进行的。 Java代码 protectedStudentgetStudent(){ Studentstudent=(Student)studentLocal.get(); if(student==null){ student=newStudent(); studentLocal.set(student); } returnstudent; } protectedvoidsetStudent(Studentstudent){ studentLocal.set(student); } accessStudent()方法需要做一些改变。通过调用getStudent()方法来获得当前线程的Student变量,如果当前线程不存在一个Student变量,getStudent方法会创建一个新的Student变量,并设置在当前线程中。 Studentstudent=getStudent(); student.setAge(age); accessStudent()方法中无需要任何同步代码。 完整的代码清单如下: TreadLocalDemo.java Java代码 publicclassTreadLocalDemoimplementsRunnable{ privatefinalstaticThreadLocalstudentLocal=newThreadLocal(); publicstaticvoidmain(String[]agrs){ TreadLocalDemotd=newTreadLocalDemo(); Threadt1=newThread(td,"a"); Threadt2=newThread(td,"b"); t1.start(); t2.start(); } /*(non-Javadoc) *@seejava.lang.Runnable#run() */ publicvoidrun(){ accessStudent(); } publicvoidaccessStudent(){ StringcurrentThreadName=Thread.currentThread().getName(); System.out.println(currentThreadName+"isrunning!"); Randomrandom=newRandom(); intage=random.nextInt(100); System.out.println("thread"+currentThreadName+"setageto:"+age); Studentstudent=getStudent(); student.setAge(age); System.out.println("thread"+currentThreadName+"firstreadageis:"+student.getAge()); try{ Thread.sleep(5000); } catch(InterruptedExceptionex){ ex.printStackTrace(); } System.out.println("thread"+currentThreadName+"secondreadageis:"+student.getAge()); } protectedStudentgetStudent(){ Studentstudent=(Student)studentLocal.get(); if(student==null){ student=newStudent(); studentLocal.set(student); } returnstudent; } protectedvoidsetStudent(Studentstudent){ studentLocal.set(student); } } 运行程序后,屏幕输出: bisrunning! threadbsetageto:0 threadbfirstreadageis:0 aisrunning! threadasetageto:17 threadafirstreadageis:17 threadbsecondreadageis:0 threadasecondreadageis:17 可见,使用ThreadLocal后,我们不需要任何同步代码,却能够保证我们线程间数据的安全。 而且,ThreadLocal的使用也非常的简单。 我们仅仅需要使用它提供的两个方法 voidset(Objectobj)设置当前线程的变量的副本的值。 Objectget()返回当前线程的变量副本 另外ThreadLocal还有一个protected的initialValue()方法。返回变量副本在当前线程的初始值。默认为null ThreadLocal是怎么做到为每个线程都维护一个变量的副本的呢? 我们可以猜测到ThreadLocal的一个简单实现 Java代码 publicclassThreadLocal { privateMapvalues=Collections.synchronizedMap(newHashMap()); publicObjectget() { ThreadcurThread=Thread.currentThread(); Objecto=values.get(curThread); if(o==null&&!values.containsKey(curThread)) { o=initialValue(); values.put(curThread,o); } returno; } publicvoidset(ObjectnewValue) { values.put(Thread.currentThread(),newValue); } publicObjectinitialValue() { returnnull; } } 由此可见,ThreadLocal通过一个Map来为每个线程都持有一个变量副本。这个map以当前线程为key。与synchronized相比,ThreadLocal是以空间换时间的策略来实现多线程程序。 Synchronized还是ThreadLocal? ThreadLocal以空间换取时间,提供了一种非常简便的多线程实现方式。因为多个线程并发访问无需进行等待,所以使用ThreadLocal会获得更大的性能。虽然使用ThreadLocal会带来更多的内存开销,但这点开销是微不足道的。因为保存在ThreadLocal中的对象,通常都是比较小的对象。另外使用ThreadLocal不能使用原子类型,只能使用Object类型。ThreadLocal的使用比synchronized要简单得多。 ThreadLocal和Synchonized都用于解决多线程并发访问。但是ThreadLocal与synchronized有本质的区别。synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。 Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离 |
相关文章推荐
- 多线程高并发访问--------synchronized和ThreadLocal的区别
- ThreadLocal与synchronized多线程并发访问区别1【转】
- java多线程基础值对象和变量的并发访问之synchronized(二)
- JAVA多线程-对象及变量的并发访问(一)synchronized详解
- java多线程之-----对象及变量的并发访问1(synchronized同步方法)
- 多线程编程核心技术读书笔记(二):对象及变量的并发访问(synchronized关键字)
- Java 多线程编程之一 进程与线程,并发和并行的区别:吃馒头的比喻
- Java多线程核心技术(二):对象及变量的并发访问访问
- 多线程之lock和synchronized的区别
- Java 多线程编程之一 进程与线程,并发和并行的区别
- 并发 并行 同步 异步 多线程的区别
- 并发 互斥 并行 同步 异步 多线程的区别
- Java多线程中Synchronized简介和Static Synchronized的区别
- Java 并发编程之Runnable和Thread实现多线程的区别
- Java多线程 chapter 2 对象及变量的并发访问
- Java中的Semaphore--用于多线程中控制资源并发访问的线程数
- 并发 并行 同步 异步 多线程 阻塞 非阻塞的区别
- 并发 并行 同步 异步 多线程的区别
- 多线程编程核心技术读书笔记(二):对象及变量的并发访问(volatile关键字)
- 并发与同步 (一) ThreadLocal与Synchronized 用哪一个好