您的位置:首页 > 编程语言 > Java开发

Java线程学习笔记之线程安全与不安全

2017-02-16 11:20 465 查看
在JDK API,有很多类上面都写着是线程安全或者线程不安全,比如StringBuilder就是线程不安全的类,在多线程的情况下,如果需要同步,则建议使用StringBuffer。

存在成员变量的类用于多线程时是不安全的,不安全体现在这个成员变量可能发生非原子性的操作,而变量定义在方法内也就是局部变量是线程安全的。在日常开发中,通常需要考虑成员变量或者说全局变量在多线程环境下,是否会引发一些问题。以下是示例:

创建一个线程不安全的类:

public class Count {
private int num;//成员变量
public  void count() {
for(int i=1;i<=10;i++){
num+=i;
}
System.out.println("线程:"+Thread.currentThread().getName()+";数据:"+num);
}
}


创建多线程并执行

public class ThreadSecurityTest {

public static void main(String[] args){
Runnable runnable = new Runnable() {
Count count = new Count();
@Override
public void run() {
count.count();
}
};
for(int i=0;i<10;i++){
new Thread(runnable).start();
}
}
}


这里,我们想要的结果是输出的值是一样的55

而实际上的输出结果是(会有不同的输出结果,反正不会是上面的):

线程:Thread-0;数据:55
线程:Thread-3;数据:165
线程:Thread-2;数据:275
线程:Thread-9;数据:495
线程:Thread-5;数据:550
线程:Thread-4;数据:220
线程:Thread-1;数据:165
线程:Thread-6;数据:330
线程:Thread-8;数据:440
线程:Thread-7;数据:385


完全乱掉,也就是说,所有的线程都在任意时刻读取和修改成员变量num的值,而且没有同步。也可以说这种错误是由于成员变量造成的

当我们把Count类的成员变量num变为方法变量的时候:

public class Count {
//private int num;
public synchronized void count() {
int num = 0;
for(int i=1;i<=10;i++){
num+=i;
}
System.out.println("线程:"+Thread.currentThread().getName()+";数据:"+num);
}
}


结果

线程:Thread-0;数据:55
线程:Thread-3;数据:55
线程:Thread-4;数据:55
线程:Thread-2;数据:55
线程:Thread-1;数据:55
线程:Thread-7;数据:55
线程:Thread-9;数据:55
线程:Thread-8;数据:55
线程:Thread-6;数据:55
线程:Thread-5;数据:55


或者我们把runnable的成员变量变为方法变量

线程:Thread-4;数据:55
线程:Thread-2;数据:55
线程:Thread-9;数据:55
线程:Thread-7;数据:55
线程:Thread-3;数据:55
线程:Thread-0;数据:55
线程:Thread-1;数据:55
线程:Thread-5;数据:55
线程:Thread-6;数据:55
线程:Thread-8;数据:55


输出都符合我们的预期。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: