java编发编程实战
前言
我们都知道,Spring创建出来的对象,默认单例的,所以,我一直在思考一个问题,为何多个线程访问单例对象并未发生并发问题?好像这个问题有点nt,于是我结合我所学到的知识分析了一下。
并发问题的原因
多线程访问共享变量,或操作一个可变状态的变量。共享变量很好理解啊,可变状态变量是什么意思呢?举个栗子:多线程访问一个对象的addOneByA()方法,给对象的变量A数值+1,单线程肯定没问题,多线程是有问题的。我们再来分析下,变量A如何+1
- 线程拿到A的变量
- 线程做+1操作
- 线程吧+1后的变量赋给A
就这三步,我们假如两个线程,同时拿到A变量的数值,然后做+1操作,最终,赋给A的时候A的数值最终只是+1,而不是+2。
线程隔离
这个是书里看到的,【每个线程都有各自的程序计数器、栈、局部变量】等。这个就很重要啊,这个说明,非共享、可变状态的变量,多线程操作是没有任何问题的,因为和隔离的。
解决并发问题
- 不在线程之间共享该状态变量。就是多线程不访问可变状态变量了呗。
- 将状态变量修改为不可变变量。就是可变状态变量,变成不可变状态了呗,理解为不可变得常量。
- 在共享、可变变量的操作【同步】,这个很重要!!!
问题、原理,解决就上面这些东西,可是并发问题,千变万化,还得具体问题具体分析,优化代码是个无底洞,CV能跑得了!
概念
并发产生各种各样的问题,为什么并发难,因为涉及的情况太多,所以要使用一些专用的名词去声明这种情况。
线程安全
何为线程安全,当多线程访问某个类、调用某个类的方法的时候,这个类始终表现出正确的行为这个就是线程安全,很宽泛的一个概念。并且不需要另加同步代码。换句话说就是,你多线程运行的结果,和单线程运行结果一样的话,就是线程安全的。
有状态和无状态
这个很重要,能判断出对象是否是线程安全还是不安全。
有状态
类存储数据,有变量,这就是有状态,多线程操作有状态的对象,可能会并发问题。
无状态
无存储数据、无变量,只是有一些方法,就是各个bean之间调用,保留任何信息。所以,这里又解决了我很久以前的疑问!以前我认为,所有的静态方法,多线程去访问的时候,都是线程不安全的。通过现在的逻辑去推断,并不是。为什么呢?静态方法,也是看状态,只要静态方法不持有【有状态的对象、或者可变状态变量】,只单单有局部变量,那么他就是安全的!
竞态条件
何为竞态条件?【先检查后执行】!详细来说,我们通过一个结果去做一个操作,B的操作依赖A当时的状态,但是A的状态马上就要改了。举个单例的例子
1 | if(a==null){ |
两个线程同时判断interface==null,那么会同时创建一个对象!这个就是竞态条件,一个结果,依赖了可能马上要消失的结果,肯定会产生很多问题,或者这样说,出不出问题,完全看运气。

