关于ThreadLocal如何保证数据线程安全

来源:互联网 发布:js 改变input type 编辑:程序博客网 时间:2024/05/05 20:18

在多线程的java环境中,我们很多使用需要一个共享内存来保证线程之间的通讯,这个在java里

面很简单,实例变量和静态变量。这也大家是在不经意间的使用方法,想都不用想都可以实现这些方法来

达到多线程共享数据的目的,这些共享数据存在一个线程安全的问题。特别是对于具有串行意义的数据,

流入请求号、事务号等。
这里有两个概念:
1.保证在一个线程中使用完这个数据之前不能让别人去修改这个字段的意义.
2.在整个线程生命周期内,保证这个数据一致性,而且不影响其他线程读取这个数据.
我们在考虑现存安全的时候,对第一种情况比较关注.例如大家都知道在对一个具有线程安全数据

访问的块加入一个synchronized.这里有些误导,大家会考虑在对大部分的线程安全操作考虑加入这个关键

字来达到不出错的目的,但是这个是一种很不明智的做法,我们很多时候在控制同步粒度的时候考虑不周,

导致大量的线程在同步阻塞,使得系统的性能大幅下降.所以我建议不到不得已少用慎用这个关键字.
对于第二种:大家或许或考虑用本地变量来保证这个特性.确实在一个方法中,我们的变量保证第

二种情况描述的特性,但是在我们复杂的环境中,往往有很多个线程在完成系统的任务,这样我们的时候不

可能用一个方法来描述一个线程的任务.例如我们在j2ee环境中,客户的请求号,我们在应用中需要用这个

号码来跟踪客户的信息.还有我们的事务,我们很多时候在系统中需要获得一个TXNID来贯穿事务.这样我们

能做到的就是使用ThreadLocal变量.
大家先看一下jdk中描述的,ThreadLocal提供了现成本地变量副本,为每个存放在这个实例中的变

量创建一个本地副本,在线程第一次方法这个变量的时候创建这个副本.而且表示,一般这个实例定义成一

个私有静态变量,供所有的线程来保存他们自己的全局资源副本.这样我们很容易想到使用它来做一个序号

发生器,当一个客户线程进来的时候给他分配一个序号,而在序号可以保存到他的请求结束:
public class SerialNum {
// The next serial number to be assigned
private static int nextSerialNum = 0;

private static ThreadLocal serialNum = new ThreadLocal() {
protected synchronized Object initialValue() {
return new Integer(nextSerialNum++);
}
};

public static int get() {
serialNum.set("")
return ((Integer) (serialNum.get())).intValue();
}
}

 
原创粉丝点击