鸟欲高飞先振翅,人求上进先读书。本文是原书的第3章 Thread安全3.2 什么是不线程安全。3.3什么是线程不安全。
3.2 什么是不安全?
当多个线程同时操作一个数据结构的时候产生了相互修改和串行的情况,没有保证数据的一致性,我们通常称之这种设计的代码为”线程不安全的“。
有这么一个场景,假设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一般都是单例共享变量的就会及其容易出现,多个用户之间的数据串掉了,从而导致最终数据库里面所需要统计的数据不对;
3.3 什么是安全?
我们还看上面的例子只对单个用户干活类: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方式。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/118121.html