Java学习:线程的安全问题
线程的安全问题
模拟卖票案例
创建三个的线程,同时开启,对共享的票进行出售

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 --;
}
解决线程安全问题的二种方案:使用同步方法
使用步骤:
- 把访问了共享数据的代码抽取出来,放到一个方法中
- 在方法上添加synchronized修饰符
格式:定义方法的格式
修饰符 synchronized 返回值类型 方法名(参数列表){
可能会出现线程安全问题的代码(访问了共享数据的代码)
}
解决线程安全问题的三种方案:使用Lock锁
java.util.concurrent.Locks.Lock接口
Lock实现提供了比使用synchronized 方法和语句可获得的更广泛的锁定操作。
Lock接口中的方法:
void Lock()获取锁
void unLock() 释放锁
java.util.concurrent.Locks.ReentrantLock implements Lock 接口
使用步骤:
- 在成员位置创建一个ReentrantLock对象
- 在可能会出现安全问题的代码前调用Lock接口中的方法Lock获取锁
- 在可能会出现安全问题的代码前调后用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学习:线程的安全问题的更多相关文章
- 【转】Java学习---线程间的通信
[原文]https://www.toutiao.com/i6572378564534993415/ 两个线程间的通信 这是我们之前的线程. 执行效果:谁抢到资源,谁运行~ 实现线程交替执行: 这里主要 ...
- Java学习之多线程(线程安全问题及线程同步)
一.线程安全问题产生前提:1.多线程操作共享数据2.线程任务中有多条代码 class Ticket implements Runnable { //2.共享数据 private int num = 1 ...
- Java多线程--线程安全问题的相关研究
在刚刚学线程的时候我们经常会碰到这么一个问题:模拟火车站售票窗口售票.代码如下: package cn.blogs.com.isole; /* 模拟火车站售票窗口售票,假设有50张余票 */ publ ...
- Java学习笔记-多线程-创建线程的方式
创建线程 创建线程的方式: 继承java.lang.Thread 实现java.lang.Runnable接口 所有的线程对象都是Thead及其子类的实例 每个线程完成一定的任务,其实就是一段顺序执行 ...
- Java核心知识点学习----线程中如何创建锁和使用锁 Lock,设计一个缓存系统
理论知识很枯燥,但这些都是基本功,学完可能会忘,但等用的时候,会发觉之前的学习是非常有意义的,学习线程就是这样子的. 1.如何创建锁? Lock lock = new ReentrantLock(); ...
- Java基础-线程安全问题汇总
Java基础-线程安全问题汇总 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.内存泄漏和内存溢出(out of memory)的区别 1>.什么是内存溢出 答:内存溢出指 ...
- Java基础-线程操作共享数据的安全问题
Java基础-线程操作共享数据的安全问题 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.引发线程安全问题 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运 ...
- java学习笔记15--多线程编程基础2
本文地址:http://www.cnblogs.com/archimedes/p/java-study-note15.html,转载请注明源地址. 线程的生命周期 1.线程的生命周期 线程从产生到消亡 ...
- java学习笔记14--多线程编程基础1
本文地址:http://www.cnblogs.com/archimedes/p/java-study-note14.html,转载请注明源地址. 多线程编程基础 多进程 一个独立程序的每一次运行称为 ...
随机推荐
- Android中实现Activity的透明背景效果
实现方式一(使用系统透明样式) 通过配置 Activity 的样式来实现,在 AndroidManifest.xml 找到要实现透明效果的 Activity,在 Activity 的配置中添加如下的代 ...
- HDP 3.1.0 集成 Sqoop2 踩坑问题记录
HDP 3.1.0 集成 Sqoop2 踩坑问题记录 本文原始地址:https://sitoi.cn/posts/65261.html 问题一 $ sqoop:000> start job -n ...
- 使用Nginx对Websocket进行反向代理
一. Nginx配置示例 http { map $http_upgrade $connection_upgrade { default upgrade; '' close; } server { li ...
- Unity 渲染教程(一):矩阵
转载:http://gad.qq.com/program/translateview/7181958 创建立方体网格.· 支持缩放.位移和旋转. · 使用变换矩阵. · 创建简单的相机投影. 这是关于 ...
- flask实战-个人博客-表单
表单 下面我们来编写所有表单类,personalBlog中主要包含下面这些表单: 登录表单: 文章表单: 评论表单: 博客设置表单: 这里仅介绍登录表单.文章表单.分类表单和评论表单,其他的表单在实现 ...
- NOIP 2002 选数
洛谷 P1036 选数 洛谷传送门 JDOJ 1297: [NOIP2002]选数 T2 JDOJ传送门 Description 已知 n 个整数 x1,x2,-,xn,以及一个整数 k(k< ...
- 有关OutputDebugString的一点儿事实
我最近花了一些时间分析OutputDebugString方法.在我的另一个实验中,我需要一个仅依赖于本机API的OutputDebugString版本.在实现它的过程中,我发现了一些关于OutputD ...
- 几个golang 静态资源嵌入包
静态资源嵌入二进制文件中,可以方便我们的软件分发(只需要简单的二进制文件就可以了),目前大部分golang 的 web 应用都是使用类似的方法. 以下是收集到的一些常见方案 github.com/go ...
- 【LG5504】[JSOI2011]柠檬
[LG5504][JSOI2011]柠檬 题面 洛谷 题解 考虑\(dp\),令\(f_i\)表示\(dp\)到第\(i\)位且在第\(i\)位分段的最大值. 我们令题面中的\(s_i\)为\(a_i ...
- sparksql基础知识二
目标 掌握sparksql操作jdbc数据源 掌握sparksql保存数据操作 掌握sparksql整合hive 要点 1. jdbc数据源 spark sql可以通过 JDBC 从关系型数据库中读取 ...