初识线程安全与线程不安全

前言

关于线程问题基本上贯穿学习的整个过程,像集合,servlet,structs,hibernate,spring等等,其都涉及到线程问题

线程安全

什么是线程安全?
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

线程安全问题都是由全局变量及静态变量引起的。

若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全

不妨来一个实例
首先是number类,里面有一个计数的全局和静态变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.zwl.test;
public class number {
private int num;
private static int count;
public void count(){
for(int i=1;i<=10;i++){
num+=i;
}
System.out.println(Thread.currentThread().getName()+":"+num);
}
public void countstatic(){
for(int i=1;i<=10;i++){
count+=i;
}
System.out.println(Thread.currentThread().getName()+":"+count);
}
}

显然我们希望每个线程都能输出的结果是55就是线程安全

线面是测试类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.zwl.test;
public class test {
public static void main(String[] args) {
Runnable runner=new Runnable() {
number num=new number();
@Override
public void run() {
num.count();
System.out.println("statis:");
num.countstatic();
}
};
for(int i=0;i<10;i++){
new Thread(runner).start();
}
}
}

这里启动十个线程,依次通过run方法输出全局和静态变量的累加和,如果是线程安全的,则应该都是55

结果如下所示

Thread-0:55
statis:
Thread-0:55
Thread-1:110
statis:
Thread-1:110
Thread-2:165
statis:
Thread-2:165
Thread-6:275
statis:
Thread-6:220
Thread-3:385
statis:
Thread-4:220
statis:
Thread-3:275
Thread-8:385
statis:
Thread-8:385
Thread-4:330
Thread-5:440
statis:
Thread-5:440
Thread-7:495
statis:
Thread-7:495
Thread-9:550
statis:
Thread-9:550

发现不是线程安全的

线程不安全

线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据

对于上面的线程不安全可以进行如下修改

解决方法:将全局变量变成局部变量(静态变量暂时不讨论)

1
2
3
4
5
6
7
public void count(){
int num = 0;
for(int i=1;i<=10;i++){
num+=i;
}
System.out.println(Thread.currentThread().getName()+":"+num);
}

最后所有的线程都输出了55

或者将new 的number放到run里面,变成局部的

1
2
3
4
5
6
7
8
@Override
public void run() {
number num=new number();
num.count();
System.out.println("statis:");
num.countstatic();
}
};

最后也能保证了线程安全了

热评文章