我们知道就面向对象来说 static所定义的相当于是这个类的共有特征,是所有对象可以进行访问的公共区域。那么我的问题是这样的:
浏览器或者客户端同时发送10个并行请求,static修饰的字段或者函数是否会出现数据混乱,例如第一个请求还没完成(期望值是A),第二个请求(期望值是B)比第一个请求先完成,最后第一个请求的数据和第二个请求的数据变成一样的B了。
因为现在的“工具类”定义是静态的,所以有此疑问。
当然,也可以通过单例解决上诉问题,但是我想知道如果不通过单例(单例会导致排队现象)是否会发生“脏读”情况。
这样估计会搞理解一些:
工具类中,static一般修饰的是方法,这个方法不依赖于自身变量,比如说,我们要做一个把大些字母全部变成小些字母的工具类,在这个构成中只有传参和返回值,静态在这里的作用可以理解为这个代码在程序中只有一份,如果这个时候有第二个调用过来,那就必须要第一个执行完。在这个过程中是不存在公共资源的赋值操作的。如果是修饰在成员变量上,那是静态变量,可以简单的理解成在程序运行时有一个公共的存储空间,如果在第一个请求过来时给这段空间赋值了A,在A还没有才做完的时候,第二个操作有赋值了B,紧接着第一次操作接着操作,那肯定是会使用B值的。
所以一般定况下,静态变量慎用,但有些时候我们真的不用避免使用静态变量,就要使用安全锁。
更好理解的是,线程安全问题的隐患是对同一块存储空间有多个线程对其同时进行读写操作,而static只是强制声明了某一块资源是公共资源。工具类是指同时读,所以不会出问题,但是变量可能会有同时读和写的操作,所以可能会出问题。
也就是说静态方法是每个请求相对独立的,并不会因为A调用了方法,B再调用就有可能导致AB目标结果值返回异常。反之静态变量的生命周期是程序运行时一直生存的,所以对他的操作会一直产生影响,直到程序停止运行。
@TylorChen: 基本上可以这么理解吧,其实确切的原因应该是,多线程调用工具类的静态方法,不会对同一空间造成写的操作,只会读;多线程可能会对静态变量造成同时写的操作,所以就会出问题。我们举个简单的例子,比如博物馆有一副蒙拉丽莎的画,和一支能在画上画图的笔。画就相当于静态变量,笔就相当于静态方法,每个人都可以拿到笔,也都可以在画上画,如果第一个人过来了,拿了笔画了一笔,把笔放下了,笔还是笔没有变,但是画变了;如果第一个人还没有来得及把画的内容复制走,第二个人来了也画了一笔,这个时候第一个人才把画拿走,就出现了第一个人拿到他并不想要的结果,出现了错误。希望这个例子能帮助你理解。
static只是静态,不是单线程,并发的时候还是需要用锁的才能保证一致,不知道这样说对不对
感谢大家的回复,其实这是一个我自己忽略掉的非常基础的一个知识。有关于static所修饰的字段、方法的特征没有清晰。静态变量不是线程安全的,而静态方法并不会导致线程不安全。对于字段而言,储存的是一个实际的值或者内存地址,所以当内容变更时会导致连锁反应。