《 Java并发编程从入门到精通》Thread安全与不安全

简介:

作者:张振华    购买链接:天猫商城  JD商城  当当书店

鸟欲高飞先振翅,人求上进先读书。本文是原书的第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方式。 

目录
相关文章
|
19天前
|
Java 编译器 开发者
深入理解Java内存模型(JMM)及其对并发编程的影响
【9月更文挑战第37天】在Java的世界里,内存模型是隐藏在代码背后的守护者,它默默地协调着多线程环境下的数据一致性和可见性问题。本文将揭开Java内存模型的神秘面纱,带领读者探索其对并发编程实践的深远影响。通过深入浅出的方式,我们将了解内存模型的基本概念、工作原理以及如何在实际开发中正确应用这些知识,确保程序的正确性和高效性。
|
16天前
|
安全 Java 编译器
Java 泛型深入解析:类型安全与灵活性的平衡
Java 泛型通过参数化类型实现了代码重用和类型安全,提升了代码的可读性和灵活性。本文深入探讨了泛型的基本原理、常见用法及局限性,包括泛型类、方法和接口的使用,以及上界和下界通配符等高级特性。通过理解和运用这些技巧,开发者可以编写更健壮和通用的代码。
|
1月前
|
安全 Java API
java安全特性
java安全特性
26 8
|
1月前
|
Java 开发者
深入探索Java中的并发编程
本文将带你领略Java并发编程的奥秘,揭示其背后的原理与实践。通过深入浅出的解释和实例,我们将探讨Java内存模型、线程间通信以及常见并发工具的使用方法。无论是初学者还是有一定经验的开发者,都能从中获得启发和实用的技巧。让我们一起开启这场并发编程的奇妙之旅吧!
22 5
|
1月前
|
算法 安全 Java
Java中的并发编程是如何实现的?
Java中的并发编程是通过多线程机制实现的。Java提供了多种工具和框架来支持并发编程。
17 1
|
1月前
|
缓存 监控 Java
Java中的并发编程:理解并应用线程池
在Java的并发编程中,线程池是提高应用程序性能的关键工具。本文将深入探讨如何有效利用线程池来管理资源、提升效率和简化代码结构。我们将从基础概念出发,逐步介绍线程池的配置、使用场景以及最佳实践,帮助开发者更好地掌握并发编程的核心技巧。
|
1月前
|
安全 Java API
【性能与安全的双重飞跃】JDK 22外部函数与内存API:JNI的继任者,引领Java新潮流!
【9月更文挑战第7天】JDK 22外部函数与内存API的发布,标志着Java在性能与安全性方面实现了双重飞跃。作为JNI的继任者,这一新特性不仅简化了Java与本地代码的交互过程,还提升了程序的性能和安全性。我们有理由相信,在外部函数与内存API的引领下,Java将开启一个全新的编程时代,为开发者们带来更加高效、更加安全的编程体验。让我们共同期待Java在未来的辉煌成就!
56 11
|
1月前
|
安全 Java API
【本地与Java无缝对接】JDK 22外部函数和内存API:JNI终结者,性能与安全双提升!
【9月更文挑战第6天】JDK 22的外部函数和内存API无疑是Java编程语言发展史上的一个重要里程碑。它不仅解决了JNI的诸多局限和挑战,还为Java与本地代码的互操作提供了更加高效、安全和简洁的解决方案。随着FFM API的逐渐成熟和完善,我们有理由相信,Java将在更多领域展现出其强大的生命力和竞争力。让我们共同期待Java编程新纪元的到来!
70 11
|
1月前
|
安全 Java 测试技术
掌握Java的并发编程:解锁高效代码的秘密
在Java的世界里,并发编程就像是一场精妙的舞蹈,需要精准的步伐和和谐的节奏。本文将带你走进Java并发的世界,从基础概念到高级技巧,一步步揭示如何编写高效、稳定的并发代码。让我们一起探索线程池的奥秘、同步机制的智慧,以及避免常见陷阱的策略。
|
1月前
|
存储 Java 程序员
优化Java多线程应用:是创建Thread对象直接调用start()方法?还是用个变量调用?
这篇文章探讨了Java中两种创建和启动线程的方法,并分析了它们的区别。作者建议直接调用 `Thread` 对象的 `start()` 方法,而非保持强引用,以避免内存泄漏、简化线程生命周期管理,并减少不必要的线程控制。文章详细解释了这种方法在使用 `ThreadLocal` 时的优势,并提供了代码示例。作者洛小豆,文章来源于稀土掘金。