线程的安全问题

模拟卖票案例
创建三个的线程,同时开启,对共享的票进行出售

public class RunnableImpl implementsc Runnable{
//定义一个多线程共享的票源
private int ticket = 100; //设置线程任务:买票
@Override
public void run(){
//使用死循环,让卖票操作重复执行
while (true){
//先判断票是否存在
if(ticket>0){
//提高安全问题出现的概率,让程序睡眠
try{
Thread.sleep(10);
}catch (InterruptedException e){
e.printStackTrace();
}
//票存在,卖票 ticket--
System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket+"张票");
ticket --;
}
}
}
} public class CaiNiao{
public static void main(String[] args){
//创建Runnable接口的实现类对象
RunnableImpl run = new RunnableImpl();
//创建Thread类对象,构造方法中传递Runnable接口的实现类对象
Thread t0 = new Thread(run);
Thread t1 = new Thread(run);
Thread t2 = new Thread(run);
//调用start方法开启多线程
t0.start();
t1.start();
t2.start();
}
}

这样会导致一个结果

  • Thread-0 -->正在卖第1张票
  • Thread-1 -->正在卖第1张票
  • Thread-2 -->正在卖第0张票

解决线程安全问题的一种方案:使用同步代码块

格式:

格式:
syncharonized(锁对象){
可能会出现线程安全问题的代码(访问了共享数据的代码)
}

注意:

  • 通过代码块中的锁对象,可以使用任意的对象
  • 但是必须要保证多个线程使用的锁对象是同一个

锁对象作用

  • 把同步代码块锁住,只让一个线程在同步代码中执行
public class RunnableImpl implementsc Runnable{
//定义一个多线程共享的票源
private int ticket = 100; //设置线程任务:买票
@Override
public void run(){
//使用死循环,让卖票操作重复执行
while (true){
//同步代码块
syncharonized(obj){
//先判断票是否存在
if(ticket>0){
//提高安全问题出现的概率,让程序睡眠
try{
Thread.sleep(10);
}catch (InterruptedException e){
e.printStackTrace();
}
//票存在,卖票 ticket--
System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket+"张票");
ticket --;
}

解决线程安全问题的二种方案:使用同步方法

使用步骤:

  1. 把访问了共享数据的代码抽取出来,放到一个方法中
  2. 在方法上添加synchronized修饰符

格式:定义方法的格式

    修饰符 synchronized 返回值类型 方法名(参数列表){
可能会出现线程安全问题的代码(访问了共享数据的代码)
}

解决线程安全问题的三种方案:使用Lock锁

java.util.concurrent.Locks.Lock接口
Lock实现提供了比使用synchronized 方法和语句可获得的更广泛的锁定操作。

Lock接口中的方法:

  void Lock()获取锁
  void unLock() 释放锁
java.util.concurrent.Locks.ReentrantLock implements Lock 接口

使用步骤:

  1. 在成员位置创建一个ReentrantLock对象
  2. 在可能会出现安全问题的代码前调用Lock接口中的方法Lock获取锁
  3. 在可能会出现安全问题的代码前调后用Lock接口中的方法unLock释放锁
//1.在成员位置创建一个ReentrantLock对象
Lock l = new ReentrantLock(); @Override
public void run(){
//使用死循环,让卖票操作重复执行
while (true){
//2. 在可能会出现安全问题的代码前调用Lock接口中的方法Lock获取锁
l.lock(); //同步代码块
syncharonized(obj){
//先判断票是否存在
if(ticket>0){
//提高安全问题出现的概率,让程序睡眠
try{
Thread.sleep(10);
}catch (InterruptedException e){
e.printStackTrace();
}
//票存在,卖票 ticket--
System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket+"张票");
ticket --;
}
//3.在可能会出现安全问题的代码前调后用Lock接口中的方法unLock释放锁
l.unLock();//无论程序释放异常,锁都会释放

Java学习:线程的安全问题的更多相关文章

  1. 【转】Java学习---线程间的通信

    [原文]https://www.toutiao.com/i6572378564534993415/ 两个线程间的通信 这是我们之前的线程. 执行效果:谁抢到资源,谁运行~ 实现线程交替执行: 这里主要 ...

  2. Java学习之多线程(线程安全问题及线程同步)

    一.线程安全问题产生前提:1.多线程操作共享数据2.线程任务中有多条代码 class Ticket implements Runnable { //2.共享数据 private int num = 1 ...

  3. Java多线程--线程安全问题的相关研究

    在刚刚学线程的时候我们经常会碰到这么一个问题:模拟火车站售票窗口售票.代码如下: package cn.blogs.com.isole; /* 模拟火车站售票窗口售票,假设有50张余票 */ publ ...

  4. Java学习笔记-多线程-创建线程的方式

    创建线程 创建线程的方式: 继承java.lang.Thread 实现java.lang.Runnable接口 所有的线程对象都是Thead及其子类的实例 每个线程完成一定的任务,其实就是一段顺序执行 ...

  5. Java核心知识点学习----线程中如何创建锁和使用锁 Lock,设计一个缓存系统

    理论知识很枯燥,但这些都是基本功,学完可能会忘,但等用的时候,会发觉之前的学习是非常有意义的,学习线程就是这样子的. 1.如何创建锁? Lock lock = new ReentrantLock(); ...

  6. Java基础-线程安全问题汇总

    Java基础-线程安全问题汇总 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.内存泄漏和内存溢出(out of memory)的区别 1>.什么是内存溢出 答:内存溢出指 ...

  7. Java基础-线程操作共享数据的安全问题

    Java基础-线程操作共享数据的安全问题 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.引发线程安全问题 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运 ...

  8. java学习笔记15--多线程编程基础2

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note15.html,转载请注明源地址. 线程的生命周期 1.线程的生命周期 线程从产生到消亡 ...

  9. java学习笔记14--多线程编程基础1

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note14.html,转载请注明源地址. 多线程编程基础 多进程 一个独立程序的每一次运行称为 ...

随机推荐

  1. VMware vSphere API开发(一)---vSphere 体系核心概念

    1.VMware SDDC        VMware 软件定义数据中心(software defined dataCenter,SDDC),包括了从最底层的VMware vSphere.软件定义存储 ...

  2. day 44

    目录 前端 什么是前端 什么是后端 web服务的本质 请求方式 HTTP协议 1.四大特性 2.数据格式 请求格式 响应格式 响应状态码 HTML 文件的后缀名 HTML的注释 HTML的文档结构 标 ...

  3. 简明conda使用指南

    目录 区分conda, anaconda, miniconda conda版本 虚拟环境 分享环境 查看某个环境的位置 列出软件包 安装软件包 删除软件包 查找软件包 conda配置 conda实践: ...

  4. 【Spring AOP】Spring AOP之你必须知道的AOP相关概念(1)

    一.什么是AOP AOP(Aspect-oriented Programming)即面向切面编程,是对OOP( Object-oriented Programming)即面向对象编程的一种补充,AOP ...

  5. sublimeText3和phpstrom使用

    一.sublimtext3 下载地址:http://www.sublimetext.com/3 1.1      安装package control 插件,用来获取和管理插件(sublime包管理工具 ...

  6. javascript 初探

    JS ,前端3剑客之一,控制HTML标签的动作.浏览器通过解释JS代码识别ta要做什么,因为在浏览器操作,所以最好使用谷歌浏览器. 参考: https://www.cnblogs.com/yuanch ...

  7. Shiro RememberMe 1.2.4 反序列化漏洞详细复现

    0x00 前言 今天上班的时候收到了一个复测的任务,打开一看,shiro反序列化漏洞,What?这是个什么东西,经百度查找后才知道,原来是Java的开发框架,好吧,还是没听说过..由于初测报告上的过程 ...

  8. Keras 训练一个单层全连接网络的线性回归模型

    1.准备环境,探索数据 import numpy as np from keras.models import Sequential from keras.layers import Dense im ...

  9. 关于交叉熵损失函数Cross Entropy Loss

    1.说在前面 最近在学习object detection的论文,又遇到交叉熵.高斯混合模型等之类的知识,发现自己没有搞明白这些概念,也从来没有认真总结归纳过,所以觉得自己应该沉下心,对以前的知识做一个 ...

  10. Eclipse调用Tomcat出错

    错误提示:The server cannot be started because one or more of the ports are invalid. Open the server edit ...