文档目录:

一、概念

二、解决方案

三、举例说明

---------------------------------------分割线:正文--------------------------------------------------------

一、概念

关注数据在多线程并发时安全问题,共享数据有修改的行为。

二、解决方案

1、线程排队执行,不能并发,即线程同步机制。

2、使用synchronized(){}线程同步代码块,()内填写需要同步的共享对象

3、局部变量永远不存在线程安全问题,因为局部变量是不会共享的

三、举例说明

1、编写程序模拟两个线程同时对同一个账户进行去取款操作

(1)变成账户类

 1 package JAVAADVANCE;
2
3 public class Account {
4 //账户与余额
5 private String actNo;
6 private double balance;
7
8 public Account(String actNo, double balance) {
9 this.actNo = actNo;
10 this.balance = balance;
11 }
12
13 public String getActNo() {
14 return actNo;
15 }
16
17 public void setActNo(String actNo) {
18 this.actNo = actNo;
19 }
20
21 public double getBalance() {
22 return balance;
23 }
24
25 public void setBalance(double balance) {
26 this.balance = balance;
27 }
28 //取款
29 public void withdraw(double money){
30 //取款之前的余额
31 double before=this.getBalance();
32 //取款之后的余额
33 double after = before-money;
34 //更新余额
35 this.setBalance(after);
36 }
37
38 }

(2)编写账户线程类

 1 package JAVAADVANCE;
2
3 public class AccountThread extends Thread {
4 //两个线程必须共享同一个账户对象
5 private Account act;
6 //通过构造方法传递过来的账户对象
7 public AccountThread(Account act){
8 this.act=act;
9 }
10 @Override
11 public void run() {
12 //run方法执行表示取款操作
13 //假设取款5000
14 double money=5000;
15 //取款
16 act.withdraw(money);
17 System.out.println(Thread.currentThread().getName()+"对账户"+act.getActNo()+"取款成功,余额为:"+act.getBalance());
18 }
19 }

(3)测试类进行取款操作

 1 package JAVAADVANCE;
2
3 public class TestAdvance38TestThreadSafe01 {
4 public static void main(String[] args) {
5 //创建账户对象,只创建一个
6 Account act=new Account("act-001",10000);
7 //创建两个线程
8 Thread t1=new AccountThread(act);
9 Thread t2=new AccountThread(act);
10 //设置name
11 t1.setName("t1");
12 t2.setName("t2");
13 //启动线程取款
14 t1.start();
15 t2.start();
16 }
17
18 }

(4)查看运行结果,一定几率出现钱被取完,余额未更新,出现线程安全问题

t2对账户act-001取款成功,余额为:5000.0
t1对账户act-001取款成功,余额为:5000.0

2、改进代码,使用线程同步机制来解决以上问题

(1)加入synchronized ()线程同步代码块

()内需要填写多线程共享的数据,才能达到多线程排队。

 1     //取款
2 public void withdraw(double money){
3 //增加线程同步机制,里面是线程同步代码块
4 synchronized (this){
5 //取款之前的余额
6 double before=this.getBalance();
7 //取款之后的余额
8 double after = before-money;
9 try {
10 Thread.sleep(1000);
11 } catch (InterruptedException e) {
12 e.printStackTrace();
13 }
14 //更新余额
15 this.setBalance(after);
16 }
17
18 }

改进后再次执行,多线程不会并发

t1对账户act-001取款成功,余额为:5000.0
t2对账户act-001取款成功,余额为:0.0

(2)whithdraw调用时候增加,synchronized ()线程同步代码块,扩大了同步范围,执行效率变低

 1     @Override
2 public void run() {
3 //run方法执行表示取款操作
4 //假设取款5000
5 double money=5000;
6 //取款
7 synchronized (act){
8 act.withdraw(money);}
9 System.out.println(Thread.currentThread().getName()+"对账户"+act.getActNo()+"取款成功,余额为:"+act.getBalance());
10 }

执行效果同上:多线程不会并发

(3)将实例方法使用synchronized

缺点:一定需要锁this,整个方法体都需要同步,可能会扩大同步范围导致程序效率过低

有点:代码比较少,简介

 1     //取款
2 public synchronized void withdraw(double money){
3 //增加线程同步机制,里面是线程同步代码块
4 // synchronized (this){
5 //取款之前的余额
6 double before=this.getBalance();
7 //取款之后的余额
8 double after = before-money;
9 try {
10 Thread.sleep(1000);
11 } catch (InterruptedException e) {
12 e.printStackTrace();
13 }
14 //更新余额
15 this.setBalance(after);
16 }

java进阶(38)--线程安全的更多相关文章

  1. Java线程间通信方式剖析——Java进阶(四)

    原创文章,同步发自作者个人博客,转载请在文章开头处以超链接注明出处 http://www.jasongj.com/java/thread_communication/ CountDownLatch C ...

  2. Java进阶(四十三)线程与进程的区别

    Java进阶(四十三)线程与进程的区别 1.线程的基本概念   概念:线程是进程中执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必 ...

  3. 【重学Java】多线程进阶(线程池、原子性、并发工具类)

    线程池 线程状态介绍 当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态.线程对象在不同的时期有不同的状态.那么Java中的线程存在哪几种状态呢?Java中的线程 状态被定 ...

  4. Java进阶(七)正确理解Thread Local的原理与适用场景

    原创文章,始自发作者个人博客,转载请务必将下面这段话置于文章开头处(保留超链接). 本文转发自技术世界,原文链接 http://www.jasongj.com/java/threadlocal/ Th ...

  5. java进阶视频分享

    更多资源和教程请关注公众号:非科班的科班. 如果觉得我写的还可以请给个赞,谢谢大家,你的鼓励是我创作的动力 课程目录介绍 01.开班仪式02.并发编程专题之多线程基础03.并发编程专题之Java内存模 ...

  6. Java进阶(五)Java I/O模型从BIO到NIO和Reactor模式

    原创文章,同步发自作者个人博客,http://www.jasongj.com/java/nio_reactor/ Java I/O模型 同步 vs. 异步 同步I/O 每个请求必须逐个地被处理,一个请 ...

  7. Java进阶(三)多线程开发关键技术

    原创文章,同步发自作者个人博客,转载请务必以超链接形式在文章开头处注明出处http://www.jasongj.com/java/multi_thread/. sleep和wait到底什么区别 其实这 ...

  8. 当我们说线程安全时,到底在说什么——Java进阶系列(二)

    原创文章,同步发自作者个人博客,转载请以超链接形式在文章开头处注明出处http://www.jasongj.com/java/thread_safe/ 多线程编程中的三个核心概念 原子性 这一点,跟数 ...

  9. Java并发3-多线程面试题

    1) 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速. 2) 线程和进程有什 ...

随机推荐

  1. WebAR in Action

    WebAR in Action WebAR (Web + AR) 增强现实 https://developer.mozilla.org/en-US/docs/Web/API/WebAR_API Web ...

  2. How to implement an accurate countdown timer with js

    How to implement an accurate countdown timer with js 如何用 js 实现一个精确的倒计时器 原理剖析 web worker js custom ti ...

  3. Java Hipster

    Java Hipster JHipster JHipster is a development platform to quickly generate, develop, & deploy ...

  4. animejs 动画库

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. ⑧SpringCloud 实战:引入 Actuator监控+整合监控页面

    Actuator是什么? Spring Boot Actuator 模块提供了生产级别的功能,比如健康检查,审计,指标收集,HTTP 跟踪等,帮助我们监控和管理Spring Boot 应用.这个模块是 ...

  6. 注解处理器APT详解

    本文转载自ANNOTATION PROCESSING 101 Introduction In this blog entry I would like to explain how to write ...

  7. 【commons-pool2源码】写前思考

    写作的初衷 工作4年多, 一直没有系统的阅读过优秀的开源代码, 所以从今年开始做一些尝试, 阅读源码并且试着将自己的理解以文章的形式输出, 从而达到以下目的: 通过阅读源码提升自身的技术水准, 通过写 ...

  8. 图文详解:Kafka到底有哪些秘密让我对它情有独钟呢?

  9. Pygame基础(1)

    Pygame是Python的一个很常用的游戏框架,今天我来讲一讲Pygame的基础知识 Pygame的官网:https://www.pygame.org/news Pygame的下载 打开cmd输入p ...

  10. 死磕hyperledger fabric源码|Order节点概述

    死磕hyperledger fabric源码|Order节点概述 文章及代码:https://github.com/blockchainGuide/ 分支:v1.1.0 前言及源码目录 Orderer ...