线程同步(Thread synchronization)
线程同步(Thread synchronization)
Member name
Password
Automatic login, forget password
You are not logged in! - login login page. Registered enterprises registered | search help.
Java Ruby AJAX Agile | Home Forum |. Blog circle | recruitment service search
Forum - > Java - > ThreadLocal and synchronized
All Hibernate, Spring, Struts, Webwork, iBATIS, enterprise application design patterns, DAO domain model, OO, Tomcat, SOA, JBoss, J2ME
Read the last topic / read the next topic
Browse 10522 times, a total of 8 pages, the current first pages, 1 [2], [3], [4], [5], [6]... [8], next page
Subject: ThreadLocal and synchronized essence post (0):: good post (0):: entry post (5):: Hidden posts (12)
Author text
Klyuan class:
Article: 136
Points: 282
Time: 2007-05-22 17:49, keywords: Spring reference, recommended collection
--------------------------------------------------------------------------------
ThreadLocal and synchronized
Java good support for multithreading. With Java, we can easily program a multithreaded program. However, the use of multithreading can cause concurrent access problems. Both synchronized and ThreadLocal are used to solve multithreaded concurrent access problems. People may be more familiar with synchronized, but much less familiar with ThreadLocal.
Concurrency problems. When an object is accessed simultaneously by two threads, there may be a thread that gets unexpected results.
A simple java class, Studnet
Code
Public, class, Student {
Private int age=0;
Public, int, getAge () {
Return this.age;
}
Public, void, setAge (int, age) {
This.age = age;
}
}
A multithreaded class, ThreadDemo.
This class has a private variable of Student, which randomly generates an integer in the run method. Then set to the student variable and read the set value from the student. Then sleep for 5 seconds, and finally read the student value of age again.
Code
Public, class, ThreadDemo, implements, Runnable{
Student student = new, Student ();
Public, static, void, main (String[], AGRS) {
ThreadDemo td = new, ThreadDemo ();
Thread, T1 = new, Thread (TD, a);
Thread, T2 = new, Thread (TD, B);
T1.start ();
T2.start ();
}
* (non-Javadoc)
* @see, java.lang.Runnable#run ()
* /
Public, void, run () {
AccessStudent ();
}
Public, void, accessStudent () {
String currentThreadName = Thread.currentThread ().GetName
();
System.out.println (currentThreadName+, is, running,...);
("first read / / System.out.println age is: (+this.student.getAge));
Random random = new, Random ();
Int age = random.nextInt (100);
System.out.
println(“线程”+ currentthreadname +”时代:“+年龄);
这个学生setage(年龄);
系统的输入(“线程”+ currentthreadname +”第一次读年龄:”+
这个学生。getage());
尝试{
线程(睡眠)(5000);
}
赶上(InterruptedException EX){
如printstacktrace();
}
系统的输入(“线”+“currentthreadname +二读年龄:“这个学生。
getage());
}
}
运行这个程序,屏幕输出如下:
正在跑步~
B在跑步~
线程B将年龄设置为:33
线程B的首读年龄是:33
将一个固定的年龄线程设置为:81
线程的第一个读取年龄是:81
螺纹B第二读年龄为:81
线程的第二读年龄是:81
需要注意的是,线程一在同一个方法中,第一次读取学生的值与第二次读取值不一致这就是出现了并发问题年龄。
同步
上面的例子,我们模似了一个并发问题。java提供了同步机制来解决并发问题。synchonzied关键字可以用来同步变量,方法,甚至同步一个代码块。
使用了同步后,一个线程正在访问同步对象时,另外一个线程必须等待。
同步同步方法
现在我们可以对accessstudent方法实施同步。
公共使用同步accessstudent()
再次运行程序,屏幕输出如下:
正在跑步~
将一个固定的年龄线程设置为:49
线程的第一个读取年龄是:49
线程的第二读年龄是:49
B在跑步~
线程B将年龄设置为:17
线程B的首读年龄是:17
螺纹B第二读年龄为:17
加上了同步后,线程B必须等待线程一执行完毕后,线程B才开始执行。
对方法进行同步的代价是非常昂贵的。特别是当被同步的方法执行一个冗长的操作这个方法执行会花费很长的时间,对这样的方法进行同步可能会使系统性能成数量级的下降。
同步同步块
在accessstudent方法中,我们真实需要保护的是学生变量,所以我们可以进行一个更细粒度的加锁我们仅仅对学生相关的代码块进行同步。
代码
同步(此){
随机=新();
年龄=随机nextInt(100);
系统的输入(“线程”+ currentthreadname +”时代:“+年龄);
这个学生setage(年龄);
系统的输入(“线程”+ currentthreadname +”第一次读年龄:”+
这个学生。getage());
尝试{
线程(睡眠)(5000);
}
赶上(InterruptedException EX){
如printstacktrace();
}
}
运行方法后,屏幕输出:
正在跑步~
将一个固定的年龄线程设置为:18
线程的第一个读取年龄是:18
B在跑步~
线程的第二读年龄是:18
线程B将年龄设置为:62
线程B的首读年龄是:62
螺纹B第二读年龄为:62
Special attention should be paid to this output.
This execution is much faster than the above method of synchronization.
Only code access to student is synchronous, while others are asynchronous with some of the code. The value of student has not been modified incorrectly. If it is in a real system, the
operation of the accessStudent method is time-consuming. The speed of using synchronization is almost as fast as without synchronization.
Using synchronous locks
Change the above example slightly, and there is a private variable count in ThreadDemo,.
Private int count=0;
In accessStudent (), the thread is accessed once each time, and the count is used to count the number of thread accesses.
Code
{try
This.count++;
Thread.sleep (5000);
}catch (InterruptedException, ex) {
Ex.printStackTrace ();
}
To simulate the thread, let it sleep 5 seconds after each addition.
The complete code for the accessStuden () method is as follows:
Code
String currentThreadName = Thread.currentThread ().GetName ();
System.out.println (currentThreadName+, is, running,...);
{try
This.count++;
Thread.sleep (5000);
}catch (InterruptedException, ex) {
Ex.printStackTrace ();
}
System.out.println ("thread", "+currentThreadName+", "read count:", +this.count);
Synchronized (this) {
Random random = new, Random ();
Int age = random.nextInt (100);
System.out.println ("thread", "+currentThreadName +", "set,
age, to:", +age);
This.student.setAge (age);
System.out.println ("thread", "+currentThreadName+", "first",
"read", "age", "is:", "+this.student.getAge");
{try
Thread.sleep (5000);
}
Catch (InterruptedException, ex) {
Ex.printStackTrace ();
}
}
System.out.println ("thread", "+currentThreadName" + "second,
read, age, is:", +this.student.getAge ());
After running the program, the screen output:
A is running!
B is running!
Thread a read count:2
Thread, a, set, age, to:49
Thread, a, first, read, age, is:49
Thread b read count:2
Thread, a, second, read, age, is:49
Thread, B, set, age, to:7
Thread, B, first, read, age, is:7
Thread, B, second, read, age, is:7
We still synchronize student objects with synchronized (this)
operations.
We need to share count failures in two threads.
So you still need to synchronize access to count.
Code
Synchronized (this) {
{try
This.count++;
Thread.sleep (5000);
}catch (InterruptedException, ex) {
Ex.printStackTrace ();
}
}
System.out.println ("thread", "+currentThreadName+", "read
count:", +this.count);
Synchronized (this) {
Random random = new, Random ();
Int age = random.nextInt (100);
System.out.println ("thread", "+currentThreadName +", "set,
age, to:", +age);
This.student.setAge (age);
System.out.
println(“线程”+ currentthreadname +”第一次读年龄:”+这个学生。getage());
尝试{
线程(睡眠)(5000);
}
赶上(InterruptedException EX){
如printstacktrace();
}
}
系统的输入(“线”+“currentthreadname +二读年龄:“这个学生。
getage());
长端currenttimemillis() =系统;
长时间=结束时间-开始时间;
系统的输入(“花费时间:”+时间+“毫秒”);
程序运行后,屏幕输出
正在跑步~
B在跑步~
线程读计数:1
将一个固定的年龄线程设置为:97
线程的第一个读取年龄是:97
线程的第二读年龄是:97
花费时间:10015毫秒
线程B读取计数:2
线程B将年龄设置为:47
线程B的首读年龄是:47
螺纹B第二读年龄为:47
花费时间:20124毫秒
我们在同一个方法中,多次使用同步(这进行加锁有可能会导致太多
额外的等待)。
应该使用不同的对象锁进行同步。
设置两个锁对象,分别用于学生和计数的访问加锁。
代码
私有对象studentlock =新object();
私有对象countlock =新object();
accessstudent()方法如下:
长时间currenttimemillis() =系统;
字符串currentthreadname =线程。currentthread()。getname();
系统。出来。println(currentthreadname +“跑~”);
/ /系统。出来。println(“先阅读年龄:”+这个学生。getage());
同步(countlock){
尝试{
这个数+ +;
线程(睡眠)(5000);
} catch(InterruptedException EX){
如printstacktrace();
}
}
系统的输入(“线程”+ currentthreadname +“阅读数:“这个数。);
同步(studentlock){
随机=新();
年龄=随机nextInt(100);
系统的输入(“线程”+ currentthreadname +”时代:“+年龄);
这个学生setage(年龄);
系统的输入(“线程”+ currentthreadname +”第一次读年龄:”+这个学生。getage());
尝试{
线程(睡眠)(5000);
}
赶上(InterruptedException EX){
如printstacktrace();
}
}
系统的输入(“线”+“currentthreadname +二读年龄:“这个学生。getage());
长端currenttimemillis() =系统;
长时间=结束时间-开始时间;
System.out.println (cost time: +spendTime + MS);
This adds two different locks to count and student.
After running the program, the screen output:
A is running!
B is running!
Thread a read count:1
Thread, a, set, age, to:48
Thread, a, first, read, age, is:48
Thread, a, second, read, age, is:48
Cost time: 10016 MS
Thread b read count:2
Thread, B, set, age, to:68
Thread, B, first, read, age, is:68
Thread, B, second, read, age, is:68
Cost time: 20046 MS
Compared with the two use of synchronized (this), the use of different object locks leads to greater performance.
Thus, synchronized is the synchronization mechanism for
implementing java. The synchronization mechanism is used to synchronize concurrent access control of the same resource by multiple threads. Ensure communication between threads.
Obviously, the main purpose of synchronization is to ensure data sharing among multi threads. Synchronization can have huge performance overhead, so synchronization should be fine grained. If synchronization is used properly, the performance overhead is negligible. The real risk of using synchronization is complexity and could undermine resource security rather than performance.
ThreadLocal
As you can see above, the use of synchronization is very complex. And synchronization brings performance degradation. Java provides another way to write multithreaded programs easily through ThreadLocal. Literally, it's easy to mistake ThreadLocal as a local variable for a thread. Other ThreadLocal does not represent the current thread, and ThreadLocal actually uses hash tables to provide a copy of each variable for each thread. So as to ensure data security among threads. Each thread's data is not accessed and destroyed by another thread.
We do the first example with ThreadLocal, but we need some change.
Student is not a private variable, but needs to be encapsulated in a ThreadLocal object. By calling the set method of ThreadLocal, ThreadLocal maintains a copy of the Student variable for each thread. So the read operation of student is
done by ThreadLocal.
Code
Protected, Student, getStudent () {
Student student = (Student) studentLocal.get ();
If (student = = null) {
Student = new, Student ();
StudentLocal.set (student);
}
Return student;
}
Protected, void, setStudent (Student, student) {
StudentLocal.set (student);
}
The accessStudent () method needs to be changed. By calling the getStudent () method to obtain the Student of the current thread variables, if the current thread does not have a Student variable, the getStudent method will create a new Student variable, and set in the current thread.
Student student = getStudent ();
Student.setAge (age);
No synchronization code is required in the accessStudent () method.
The complete code list is as follows:
TreadLocalDemo.java
Code
Public, class, TreadLocalDemo, implements, Runnable {
Private, final, static, ThreadLocal, studentLocal = new, ThreadLocal ();
Public, static, void, main (String[], AGRS) {
TreadLocalDemo td = new, TreadLocalDemo ();
Thread, T1 = new, Thread (TD, a);
线程=新线程(TD,“B”);
start() T1;
start() T2;
}
/ *(非Javadoc)
*“看lang.runnable # run() java。
* /
run() { public void
accessstudent();
}
accessstudent() { public void
字符串currentthreadname =线程。currentthread()。getname();
系统。出来。println(currentthreadname +“跑~”);
随机=新();
年龄=随机nextInt(100);
系统的输入(“线程”+ currentthreadname +”时代:“+年龄);
学生= getstudent();
学生setage(年龄);
系统的输入(“线程”+ currentthreadname +”第一次读年龄:”+
学生。getage());
尝试{
线程(睡眠)(5000);
}
赶上(InterruptedException EX){
如printstacktrace();
}
系统的输入(“线”+“currentthreadname +二读年龄:”+学生。
getage());
}
保护学生getstudent() {
学生studentlocal get() =(学生);
如果(学生= NULL){
学生=新student();
studentlocal集(学生);
}
返回的学生;
}
protected void setstudent(学生){
studentlocal集(学生);
}
}
运行程序后,屏幕输出:
B在跑步~
线程B将年龄设置为:0
线程B的首读年龄是:0
正在跑步~
将一个固定的年龄线程设置为:17
线程的第一个读取年龄是:17
螺纹B第二读年龄为:0
线程的第二读年龄是:17
可见,使用ThreadLocal后,我们不需要任何同步代码,却能够保证
我们线程间数据的安全。
而且,ThreadLocal的使用也非常的简单。
我们仅仅需要使用它提供的两个方法
空集(对象)设置当前线程的变量的副本的值。
对象get()返回当前线程的变量副本
另外ThreadLocal还有一个保护的initialvalue()方法。返回变量副本在当前线程的初始值默认为空。
ThreadLocal是怎么做到为每个线程都维护一个变量的副本的呢,
我们可以猜测到ThreadLocal的一个简单实现
代码
公共类ThreadLocal
{
私人地图值=集合。synchronizedmap(新hashmap());
公共对象get()
{
螺纹curthread = currentthread()线程;
对象=价值得到(curthread);
如果(= =~价值观。
containsKey(curthread))
{
O = initialvalue();
值。把(curthread,O);
}
回来啊;
}
公共无效组(目标价值)
{
值。把(线程。currentthread(),价值);
}
公共对象initialvalue()
{
返回null;
}
}
由此可见,ThreadLocal通过一个地图来为每个线程都持有一个变量副本。这个地图以当前线程为关键。与同步相比,ThreadLocal是以空间换时间的策略来实现多线程程序。
同步还是ThreadLocal,
以空间换取时间ThreadLocal,提供了一种非常简便的多线程实现方式。因为多个线程并发访问无需进行等待,所以使用ThreadLocal会获得更大的性能。虽然使用ThreadLocal会带来更多的内存开销,但这点开销是微不足道的。因为保存在ThreadLocal中的对象,通常都是比较小的对象。另外使用ThreadLocal不能使用原子类型,只能使用类型的使用比同步要简单得多ThreadLocal对象。
和都用于解决多线程并发访问ThreadLocal的同步更新。但是ThreadLocal有本质的区别与同步。同步是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而同步却正好相反,它用于在多个线程间通信时能够获得数据共享。
同步用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。
当然ThreadLocal并不能替代同步,它们处理不同的问题域。同步用于实现同步机制,比ThreadLocal更加复杂。
声明:javaeye文章版权属于作者,受法律保护。没有作者书面许可不得转载若作者同意转载,必须以超链接形式标明文章原始出处和作者。
-----------------------------------------------------------
---------------------
相关文章:春天下Hibernate多数据库解决
方案
气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载
,以及跨库事务的尝试(已合并)倒底该怎么写道的单元测试,
推荐链接:免费下载IBM社区版软件,体验高效开发。京沪穗蓉四地免费注册,SOA技术高手汇聚交锋。
返回顶端1楼最后更新:2007-05-22优势
chamjoneu等级:初级会员
文章:15
积分:78
时间:2007-05-22 19:34评级:(0位会员评分)引用推荐收藏
-----------------------------------------------------------
---------------------
春天的transactionsynchronizationmanager也是用的ThreadLocal这一阵在读原码解决ZK里opensessioninview问题谢谢LZ分享
返回顶端2楼最后更新:2007-05-22 19:37
我来评分:请先登录
魔法等级:
文章:108
积分:118
时间:2007-05-22 20:44评级:(1位会员评分)引用推荐收藏
-----------------------------------------------------------
---------------------
那如果当前有2000个用户登陆,那么就会有2000个变量副本吧,如果不是存放什么大的对象到是没什么问题,要是存放大的对象,该怎么办呢,
返回顶端3楼最后更新:那个2007-05-24
我来评分:请先登录
javastudy等级:初级会员
性别:
文章:450
积分:0
来自:北京
圈子:英语学习
时间:2007-05-22 21:05评级:(1位会员评分)引用推荐收藏
-----------------------------------------------------------
---------------------
Hibernate会话用的是ThreadLocal中的,
返回顶端4楼最后更新:韩国工商22:02
我来评分:请先登录
XML等级:初级会员
文章:322
积分:85
圈子:八婆们的八卦堡^ _ ^
时间:2007-05-22 21:19评级:(0位会员评分)引用推荐收藏
-----------------------------------------------------------
---------------------
LZ把概念搞错了,ThreadLocal就是ThreadLocal,和同步完全没有关系。
解决的是同一个线程内的资源共享问题ThreadLocal,而同步解决的是多个线程间的资源共享问题,两个问题没有可比性。
返回顶端5楼最后更新:2007-05-22 21:19
我来评分:请先登录
等级市革力司:
性别:
文章:354
积分:703
来自:杭州
圈子:英语学习
时间:2007-05-22 21:22评级:(0位会员评分)引用推荐收藏
-----------------------------------------------------------
---------------------
连共享都谈不上ThreadLocal,其他线程根本无法读取到当前线程里的ThreadLocal里的数据
当然也不会出现竞争条件。
返回顶端6楼最后更新:2007-05-22 21:23
我来评分:请先登录
shaucle等级:
性别:
文章:394
积分:413
来自:上海
圈子:javaeye水源
时间:2007-05-23数字评级:(0位会员评分)引用推荐收藏
-----------------------------------------------------------
---------------------
是同线程的单例ThreadLocal
transactionsynchronizationmanager(ThreadLocal)和java线程中的同步是两码事。
文章好长„
返回顶端7楼最后更新:2007-05-23数字
我来评分:请先登录
nihongye等级:
文章:594
积分:1413
圈子:美女PP和PLMM
时间:“2007-05-23评级:(0位会员评分)引用推荐收藏
-----------------------------------------------------------
---------------------
写道市革力司
连共享都谈不上ThreadLocal,其他线程根本无法读取到当前线程里的ThreadLocal里的数据
当然也不会出现竞争条件。
线程1:
threadlocale1集(发生)。
这么..(发生)
2:
threadlocale12集(发生)。
这么..(发生)
返回顶端8楼最后更新:“2007-05-23
我来评分:请先登录
klyuan等级:
文章:136
积分:282
时间:2007-05-23 09:06评级:(1位会员评分)引用推荐收藏
-----------------------------------------------------------
---------------------
魔法写道
那如果当前有2000个用户登陆,那么就会有2000个变量副本吧,如果不是存放什么大的对象到是没什么问题,要是存放大的对象,该怎么办呢,
一般情况下是不会存放大对象滴~
返回顶端9楼最后更新:2007-06-07 10:27
我来评分:请先登录
klyuan等级:
文章:136
积分:282
时间:2007-05-23 09:07评级:(1位会员评分)引用推荐收藏
-----------------------------------------------------------
---------------------
XML写道
LZ把概念搞错了,ThreadLocal就是ThreadLocal,和同步完全没有关系。
解决的是同一个线程内的资源共享问题ThreadLocal,而同步解决的是多个线程间的资源共享问题,两个问题没有可比性。
我想我的概念没有搞错可能是你没有看完全文而已~~
我没有说ThreadLocal是同步~~~
返回顶端10楼最后更新:2007-06-07 10:27
我来评分:请先登录
共8页,当前第1页1 [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ]„[ 8 ]下
一页
论坛-> java -> ThreadLocal与同步
跳转论坛:java Ruby AJAX软件开发和项目管理综合技术招聘求职海阔天空入门讨论行业解决方案博客论坛圈子论坛微软.NET
推荐javaeye
免费下载IBM社区版软件,体验高效开发。
京沪穗蓉四地免费注册,SOA技术高手汇聚交锋。快速回复引用上一条消息(Alt + S)提交
广告服务| javaeye黑板报|网站地图|关于我们|服务条款|联系我们|友情链接
,2003-2007年javaeye.com。版权所有。上海炯耐计算机软件有限公司[沪ICP备05023328号]