Thread安全与不安全
2015-10-18 19:30
323 查看
1 什么是不安全?
当多个线程同时操作一个数据结构的时候产生了相互修改和串行的情况,没有保证数据的一致性,我们通常称之这种设计的代码为”线程不安全的“。
有这么一个场景,假设5个用户,都来给一个数字加1的工作,那么最后应该是得到加5的结果;看一下下面的事例;
单个用户干活类:Count ;
public class Count {
public int num = 0;
public void add() {
try {
Thread. sleep(5l);//模仿用户干活
} catch (InterruptedException e) {
}
num += 1;
System. out.println(Thread.currentThread().getName() + “-” + num);
}
}
用户类,干Count 的活;
package demo.thread;
public class ThreadA extends Thread {
private Count count ;
public ThreadA(Count count) {
this.count =count;
}
public void run() {
count.add();
}
}
5个人干完活:最后的值;
package demo.thread;
public class ThreadMain {
public static void main(String[] args) {
Count count = new Count();
for(int i=0;i<5;i++) {
ThreadA task = new ThreadA(count);
task.start();
}
try {
Thread. sleep(100l);//等5个人干完活
} catch (InterruptedException e) {
e.printStackTrace();
}
System. out.println(“5个人干完活:最后的值4″ +count .num );
}
}
运行结果如下:(由于多线程,有不安全问题,其实每次运行下面的结果都是不一样的)
Thread-1-1
Thread-0-1
Thread-3-3
Thread-4-2
Thread-2-3
5个人干完活:最后的值:3
可见不是咱们想要的结果,这就是典型的线程不安全问题;而我们实际工作中,特别是web项目Service和servlet一般都是单例共享变量的就会及其容易出现,多个用户之间的数据串掉了,从而导致最终数据库里面所需要统计的数据不对;
2 什么是安全?
我们还看上面的例子只对单个用户干活类:Count ;做如下修改 添加synchronized 关键字;
package demo.thread;
public class Count {
public int num = 0;
public synchronized void add() {
try {
Thread. sleep(5l);//模仿用户干活
} catch (InterruptedException e) {
}
num += 1;
System. out.println(Thread.currentThread().getName() + “-” + num);
}
}
运行结果如下:
Thread-0-1
Thread-4-2
Thread-3-3
Thread-2-4
Thread-1-5
5个人干完活:最后的值5
而这次,每次干活都是一样的结果,这就叫线程安全,就是不管多少个用户过来,都保证咱们的数据的高度一致性和准确性就叫线程安全的;这里我们引用了synchronized 的同步锁的机制,这个后面会讲到,来保证了我们的线程安全性;
什么是线程安全性呢?是不是一定要加锁才是线程安全性的呢?个人感觉只要你代码里面没有变量互串,线程之间互不影响,例如server的设计方法,就是线程安全的,例如上面五个人干了同一件事情,如果让5个人干5件不一样的事情,或者1个人干5件事情,那也是安全的。而不安全在java工作中主要针对单例模式的应用而言的,怎么保证一件事情被一群人干完,又快又正确;
想实现线程安全大概有三种方法:
1:多实例,也就是不用单例模式了。
2:使用java.util.concurrent下面的类库。
3:使用锁机制synchronized,lock方式。
当多个线程同时操作一个数据结构的时候产生了相互修改和串行的情况,没有保证数据的一致性,我们通常称之这种设计的代码为”线程不安全的“。
有这么一个场景,假设5个用户,都来给一个数字加1的工作,那么最后应该是得到加5的结果;看一下下面的事例;
单个用户干活类:Count ;
public class Count {
public int num = 0;
public void add() {
try {
Thread. sleep(5l);//模仿用户干活
} catch (InterruptedException e) {
}
num += 1;
System. out.println(Thread.currentThread().getName() + “-” + num);
}
}
用户类,干Count 的活;
package demo.thread;
public class ThreadA extends Thread {
private Count count ;
public ThreadA(Count count) {
this.count =count;
}
public void run() {
count.add();
}
}
5个人干完活:最后的值;
package demo.thread;
public class ThreadMain {
public static void main(String[] args) {
Count count = new Count();
for(int i=0;i<5;i++) {
ThreadA task = new ThreadA(count);
task.start();
}
try {
Thread. sleep(100l);//等5个人干完活
} catch (InterruptedException e) {
e.printStackTrace();
}
System. out.println(“5个人干完活:最后的值4″ +count .num );
}
}
运行结果如下:(由于多线程,有不安全问题,其实每次运行下面的结果都是不一样的)
Thread-1-1
Thread-0-1
Thread-3-3
Thread-4-2
Thread-2-3
5个人干完活:最后的值:3
可见不是咱们想要的结果,这就是典型的线程不安全问题;而我们实际工作中,特别是web项目Service和servlet一般都是单例共享变量的就会及其容易出现,多个用户之间的数据串掉了,从而导致最终数据库里面所需要统计的数据不对;
2 什么是安全?
我们还看上面的例子只对单个用户干活类:Count ;做如下修改 添加synchronized 关键字;
package demo.thread;
public class Count {
public int num = 0;
public synchronized void add() {
try {
Thread. sleep(5l);//模仿用户干活
} catch (InterruptedException e) {
}
num += 1;
System. out.println(Thread.currentThread().getName() + “-” + num);
}
}
运行结果如下:
Thread-0-1
Thread-4-2
Thread-3-3
Thread-2-4
Thread-1-5
5个人干完活:最后的值5
而这次,每次干活都是一样的结果,这就叫线程安全,就是不管多少个用户过来,都保证咱们的数据的高度一致性和准确性就叫线程安全的;这里我们引用了synchronized 的同步锁的机制,这个后面会讲到,来保证了我们的线程安全性;
什么是线程安全性呢?是不是一定要加锁才是线程安全性的呢?个人感觉只要你代码里面没有变量互串,线程之间互不影响,例如server的设计方法,就是线程安全的,例如上面五个人干了同一件事情,如果让5个人干5件不一样的事情,或者1个人干5件事情,那也是安全的。而不安全在java工作中主要针对单例模式的应用而言的,怎么保证一件事情被一群人干完,又快又正确;
想实现线程安全大概有三种方法:
1:多实例,也就是不用单例模式了。
2:使用java.util.concurrent下面的类库。
3:使用锁机制synchronized,lock方式。
相关文章推荐
- Linux汇编语言及嵌入式汇编
- hive中Specified key was too long; max key length is 767 bytes问题解决
- HDU——2018 母牛的故事
- C和指针 (pointers on C)——第十四章:预处理器
- UVa1382--Distant Galaxy(离散化+扫描线)
- HP ALM 测试管理中心用户创建:
- 主线程与子线程之间相互通信
- 收集 天创恒达高清采集卡TC-5A0N7
- uft练习
- ieee浮点
- web工程中各类地址的写法
- linux目录解释
- poj 3320 Jessica's Reading Problem 【尺取法】
- leetcode #66 Plus One
- 基于Theano的深度学习(Deep Learning)框架Keras学习随笔-10-回调
- 软件设计之用户界面设计
- 传教士和野人问题
- 传教士和野人问题
- Android开发之ImageView通过matrix实现两点缩放和图片拖动
- # Linux Whois3获取 运营商信息