Android-多线程安全问题-synchronized
先看一个售票案例Demo,多线程程序对共享数据操作引发的安全问题:
package android.java.thread09; /**
* 售票线程
*/
class Booking implements Runnable { /**
* 模拟票的总算 10张票
*/
private int ticket = 10; @Override
public void run() { while (true) { if (ticket > 0) {
// 让线程在这里停一下,会更加容易复现线程的安全问题,就算不加这行代码,安全问题依然有
try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("名称:" + Thread.currentThread().getName() + "窗口卖出第" + ticket + "张票");
ticket--;
} } }
} /**
* 售票案例
*/
public class BookingTest { public static void main(String[] args) { /**
* 定义Runnable实现类Booking,此实现类Booking不是线程,此实现类Booking给四个Thread去执行的
*/
Runnable booking = new Booking(); // 实例化线程对象
Thread thread1 = new Thread(booking); // 此实现类Booking给Thread去执行的
Thread thread2 = new Thread(booking); // 此实现类Booking给Thread去执行的
Thread thread3 = new Thread(booking); // 此实现类Booking给Thread去执行的
Thread thread4 = new Thread(booking); // 此实现类Booking给Thread去执行的 // 开启启动线程
thread1.start(); // 启动第Thread-0窗口 执行卖票任务
thread2.start(); // 启动第Thread-1窗口 执行卖票任务
thread3.start(); // 启动第Thread-2窗口 执行卖票任务
thread4.start(); // 启动第Thread-3窗口 执行卖票任务 } }
打印的日志结果,注意:⚠️ 没有打印的日志结果都不同,这是CPU对线程非常快速的切换造成的,哪个线程先有执行权 就执行哪个线程 都是随机的
名称:Thread-0窗口卖出第10张票
名称:Thread-3窗口卖出第9张票
名称:Thread-1窗口卖出第8张票
名称:Thread-2窗口卖出第7张票
名称:Thread-0窗口卖出第6张票
名称:Thread-3窗口卖出第5张票
名称:Thread-2窗口卖出第4张票
名称:Thread-1窗口卖出第4张票
名称:Thread-2窗口卖出第2张票
名称:Thread-0窗口卖出第1张票
名称:Thread-3窗口卖出第1张票
名称:Thread-1窗口卖出第-1张票
名称:Thread-2窗口卖出第-2张票
CPU的随机性,到底切换到哪个线程,到底执行哪个线程代码的多少行,等等,都是随机的
分析原因,为什么会出现以上日志打印的各个情况呢,为什么会出现 0张票 -1张票 这种情况呢?,看以下CPU执行线程的随机性就明白了
通过以上画图分析原因,造成安全问题的有以下两个因素:
1.线程任务中,发现有共享数据,例如:ticket。
2.多线程操作共享数据,例如:ticket。
造成的原因是:Thread-0在对共享数据操作过程中,CPU执行了Thread-1对共享数据操作, 相当于:我在数钱,突然我出去有事了,然后有个人拿了500块钱,等我在回来数钱的时候,就已经发生是数据安全问题
解决多线程安全问题,synchronize 加同步代码块,同步代码块:synchronize{ 操作共享数据的代码 }
package android.java.thread09; /**
* 售票线程
*/
class Booking implements Runnable { /**
* 模拟票的总算 10张票
*/
private int ticket = 10; @Override
public void run() { while (true) { /**
* 加入了同步代码块的代码synchronized,
* 不管CPU如何疯狂的切换执行,
* 只要同步代码块里面的代码没有执行完,
* 就不准其他线程进来执行
* 这样就保证了多线程操作共享数据的安全新
*/
synchronized (Booking.class) { // 同步操作共享数据的代码 if (ticket > 0) { // 让线程在这里停一下,会更加容易复现线程的安全问题,就算不加这行代码,安全问题依然有
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
} System.out.println("名称:" + Thread.currentThread().getName() + "窗口卖出第" + ticket + "张票");
ticket--;
}
} } }
} /**
* 售票案例
*/
public class BookingTest { public static void main(String[] args) { /**
* 定义Runnable实现类Booking,此实现类Booking不是线程,此实现类Booking给四个Thread去执行的
*/
Runnable booking = new Booking(); // 实例化线程对象
Thread thread1 = new Thread(booking); // 此实现类Booking给Thread去执行的
Thread thread2 = new Thread(booking); // 此实现类Booking给Thread去执行的
Thread thread3 = new Thread(booking); // 此实现类Booking给Thread去执行的
Thread thread4 = new Thread(booking); // 此实现类Booking给Thread去执行的 // 开启启动线程
thread1.start(); // 启动第Thread-0窗口 执行卖票任务
thread2.start(); // 启动第Thread-1窗口 执行卖票任务
thread3.start(); // 启动第Thread-2窗口 执行卖票任务
thread4.start(); // 启动第Thread-3窗口 执行卖票任务 } }
以下日志结果,是CPU随机执行到哪个线程,就哪个线程打印,CPU执行线程的随机性很重要

以下日志结果,是CPU随机执行到哪个线程,就哪个线程打印,CPU执行线程的随机性很重要

以下日志结果,是CPU随机执行到哪个线程,就哪个线程打印,CPU执行线程的随机性很重要

.........
Android-多线程安全问题-synchronized的更多相关文章
- java多线程以及Android多线程
Java 多线程 线程和进程的区别 线程和进程的本质:由CPU进行调度的并发式执行任务,多个任务被快速轮换执行,使得宏观上具有多个线程或者进程同时执行的效果. 进程:在操作系统来说,一个运行的程序或者 ...
- Android多线程分析之四:MessageQueue的实现
Android多线程分析之四:MessageQueue的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前面两篇文章<Androi ...
- Android多线程分析之三:Handler,Looper的实现
Android多线程分析之三:Handler,Looper的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前文<Android多 ...
- Android多线程分析之二:Thread的实现
Android多线程分析之二:Thread的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前文<Android多线程分析之一 ...
- 无废话Android之smartimageview使用、android多线程下载、显式意图激活另外一个activity,检查网络是否可用定位到网络的位置、隐式意图激活另外一个activity、隐式意图的配置,自定义隐式意图、在不同activity之间数据传递(5)
1.smartimageview使用 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&q ...
- java基础知识回顾之java Thread类学习(四)--java多线程安全问题(锁)
上一节售票系统中我们发现,打印出了错票,0,-1,出现了多线程安全问题.我们分析为什么会发生多线程安全问题? 看下面线程的主要代码: @Override public void run() { // ...
- android 多线程断点续传下载
今天跟大家一起分享下Android开发中比较难的一个环节,可能很多人看到这个标题就会感觉头很大,的确如果没有良好的编码能力和逻辑思维,这块是很难搞明白的,前面2次总结中已经为大家分享过有关技术的一些基 ...
- Android多线程及异步处理问题
1.问题提出 1)为何需要多线程? 2)多线程如何实现? 3)多线程机制的核心是啥? 4)到底有多少种实现方式? 2.问题分析 1)究其为啥需要多线程的本质就是异步处理,直观一点说就是不要让用户感觉到 ...
- 多线程安全问题之Lock显示锁
package com.hls.juc; import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.Reentr ...
随机推荐
- UI设计中颜色的前进色与后退色
暖色调的颜色属于前进色.膨胀色可以使物体的视觉效果变大,而收缩色可以使物体的视觉效果变小. 颜色的另外一种效果.有的颜色看起来向上凸出,而有的颜色看起来向下凹陷,其中显得凸出的颜色被称为前进色,而 ...
- JSP概述、API、注释
JSP自带的API包含4个包,可通过Tomcat的官网查看,JSP和EL的API是分开的 javax.servlet.jsp // 包含用于Servlet/JSP容器将JSP页面翻译为Servlet的 ...
- Imageview 按比例适应屏幕大小
DisplayMetrics dm = new DisplayMetrics();//取得窗口属性getWindowManager().getDefaultDisplay().getMetrics(d ...
- 【Go】 Go 语言环境安装
安装环境/工具 1.Linux(CentOS 7.4版) 2.go1.11.2.linux-amd64.tar Go 语言环境安装 1.下载安装包 安装包下载地址为:https://golang.or ...
- 2017多校1 hdu-Balala Power!
其实这道题的思路挺简单的,就是找在第一位置没有出现过并且权值小的那个字母为0. 把a~z按照权值排序,其实难就难在这里,权值很大我们怎么给他排序. 其实可以开个数组来存他们每位数是多少,然后给他们比个 ...
- kbmmw 5.06.20 发布
经过1个多月的测试,终于发布正式版. 5.06.20 July 11 2018 Important notes (changes that may break existing c ...
- oracle in 多个字段
oracle 使用in的时候使用多个字段 这个也是刚需啊. 最近有个需求,在一堆商品里面过滤出一些特定的商品类型.供应商的商品(同时满足). 需要的数量不多,但是可能会变化,所以做了两个配置表. 商品 ...
- mac os 下 Android Studio设置真机调试
http://www.cnblogs.com/developer-wang/p/6719555.html 如果没有 .bash_profile 只需要创建 .bash_profile,然后增加andr ...
- ASP.NET WebApi 基于分布式Session方式实现Token签名认证(发布版)
一.课程介绍 明人不说暗话,跟着阿笨一起学玩WebApi!开发提供数据的WebApi服务,最重要的是数据的安全性.那么对于我们来说,如何确保数据的安全将会是需要思考的问题.在ASP.NETWebSer ...
- 移动赋值运算符(c++11)
1.概念 1)移动赋值运算符是一个重载的赋值运算符,参数为自身类的右值引用,返回值自身类的左值引用,由于不抛出任何异常,用noexcept指定(如果定义在类的外面,那么定义也要用noexcept指定) ...

