《 Java并发编程从入门到精通》Thread安全与不安全
鸟欲高飞先振翅,人求上进先读书。本文是原书的第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方式。
相关文章
- Java要抛弃祖宗的基业,Java程序员危险了!
- 十大 Java 语言特性
- JVM 三色标记算法,原来是这么回事!
- 聊聊 Spring 事务控制策略以及 @Transactional 失效问题避坑
- 写给 Java 程序员的前端 Promise 教程
- 写给 Java 程序员的前端 Promise 教程,你学会了吗?
- Java 中为什么不全部使用 Static 方法?
- Java 池化技术你了解多少?
- Java 服务 Docker 容器化优秀实践
- Spring Boot + EasyExcel导入导出,简直太好用了!
- 我们一起聊聊 Java 内存泄漏
- CentOS 下安装 Docker 极简教程
- JDK 19 功能集冻结:Java 19 只有七个新特性
- 关于 CMS 垃圾回收器,你真的懂了吗?
- 为什么会有这么多编程语言?
- 改善Java代码的八个建议
- 接口流量突增,如何做好性能优化?
- Java 以编程方式创建JAR文件
- POJO、Java Bean是如何定义的
- Spring 的 Bean 明明设置了 Scope 为 Prototype,为什么还是只能获取到单例对象?