先看一个售票案例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的更多相关文章

  1. java多线程以及Android多线程

    Java 多线程 线程和进程的区别 线程和进程的本质:由CPU进行调度的并发式执行任务,多个任务被快速轮换执行,使得宏观上具有多个线程或者进程同时执行的效果. 进程:在操作系统来说,一个运行的程序或者 ...

  2. Android多线程分析之四:MessageQueue的实现

    Android多线程分析之四:MessageQueue的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前面两篇文章<Androi ...

  3. Android多线程分析之三:Handler,Looper的实现

    Android多线程分析之三:Handler,Looper的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前文<Android多 ...

  4. Android多线程分析之二:Thread的实现

    Android多线程分析之二:Thread的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处   在前文<Android多线程分析之一 ...

  5. 无废话Android之smartimageview使用、android多线程下载、显式意图激活另外一个activity,检查网络是否可用定位到网络的位置、隐式意图激活另外一个activity、隐式意图的配置,自定义隐式意图、在不同activity之间数据传递(5)

    1.smartimageview使用 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&q ...

  6. java基础知识回顾之java Thread类学习(四)--java多线程安全问题(锁)

    上一节售票系统中我们发现,打印出了错票,0,-1,出现了多线程安全问题.我们分析为什么会发生多线程安全问题? 看下面线程的主要代码: @Override public void run() { // ...

  7. android 多线程断点续传下载

    今天跟大家一起分享下Android开发中比较难的一个环节,可能很多人看到这个标题就会感觉头很大,的确如果没有良好的编码能力和逻辑思维,这块是很难搞明白的,前面2次总结中已经为大家分享过有关技术的一些基 ...

  8. Android多线程及异步处理问题

    1.问题提出 1)为何需要多线程? 2)多线程如何实现? 3)多线程机制的核心是啥? 4)到底有多少种实现方式? 2.问题分析 1)究其为啥需要多线程的本质就是异步处理,直观一点说就是不要让用户感觉到 ...

  9. 多线程安全问题之Lock显示锁

    package com.hls.juc; import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.Reentr ...

随机推荐

  1. 用户态处理arp、ndisc neighbour solication 报文

    问题背景: 想要协议栈给不是接口ip的报文,ipv4回复arp request,ipv6回复 ndisc solication. #include <stdio.h> //调用该函数成为一 ...

  2. where

    (二)WHERE //where不单独使用,与match,optional match,start,with搭配 where 与match,optional match 一起用,表示约束 where ...

  3. DataTable xml 互相转换

    //测试方法 public static DataTable Test() { string savePath = System.AppDomain.CurrentDomain.BaseDirecto ...

  4. hehe,网易邮箱已经流氓到这个地步了

    网易邮箱现在感觉作死,申请个邮箱还要下载你的APP,好,你牛逼,再见. 这是态度的问题. 最近丢了5亿的用户信息死不承认,撞库能把密保问题给撞出来? 如果真是撞库的话,丁三石养猪也已经感染口蹄疫了吧.

  5. maven 介绍(zz )

    Maven 编辑     目录 1简介 2特点 3常用命令 4推荐书籍 5Win7配置 6生命周期     1   1简介 Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构 ...

  6. Mac下Maven安装与配置

    Mac下Maven安装与配置 下载maven http://maven.apache.org/download.cgi main->download菜单下的Files 下载后解压在Documen ...

  7. C语言基础第五次作业

    题目7-2 统计一行文本的单词个数 1.实验代码 #include <stdio.h> int main() { char a; ,countword=; ){ scanf("% ...

  8. load data会被当成一个事务处理ERROR 1197

    问题现象: l有一份csv格式的文件,大小在14G左右.max_binlog_cache_size=4G. 登录mysql实例,选择对应的表通过load data往指定表里导数.大概20分钟左右,报以 ...

  9. ubuntu server 在 virtualbox中安装增强包

    原文链接:http://luzl.iteye.com/blog/1010597 首先说下增强包能干什么,在desktop下面有了增强包桌面就能变大了,在server下也是类似,那个黑屏就能变大了,还有 ...

  10. MIT Molecular Biology 笔记7 调控RNA

    视频  https://www.bilibili.com/video/av7973580/ 教材 Molecular biology of the gene 7th edition  J.D. Wat ...