Java学习之多线程(线程安全问题及线程同步)
一、线程安全问题产生前提:
1、多线程操作共享数据
2、线程任务中有多条代码
class Ticket implements Runnable
{
//2.共享数据
private int num = 100; public void run()
{
while(true)
{
//3.多条代码
if(num > 0)
{
try{Thread.sleep(10);}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"==="+num--);
}
}
}
} class TicketDemo
{
public static void main(String[] args)
{
Ticket t = new Ticket();
//1.多线程操作同一个对象
Thread t1 =new Thread(t);
Thread t2 =new Thread(t);
Thread t3 =new Thread(t);
Thread t4 =new Thread(t); t1.start();
t2.start();
t3.start();
t4.start();
}
}
运行结果:

出现线程安全问题了
二、解决线程安全问题
解决线程安全问题的两种方式:
①、同步代码块
格式:
synchronized(对象)
{
//需要被同步的代码;
... ...
}
解决上面线程安全问题的代码:
class Ticket implements Runnable
{
//2.共享数据
private int num = 100;
//同步锁:对象
private Object o=new Object();
public void run()
{
while(true)
{
synchronized(o)
{
//3.多条代码
if(num > 0)
{
try{Thread.sleep(10);}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"==="+num--);
}
}
}
}
}
结果:

解决原理:多线程在使用同步代码块时,使用了同一个同步锁(Object的对象)
②、同步函数
格式:
public synchronized 方法返回值类型 方法名(参数列表)
{
... ...
}
2.1、非静态同步函数
代码:
class Ticket implements Runnable
{
//2.共享数据
private int num = 100;
//同步锁:对象
//private Object o=new Object();
public void run()
{
while(true)
{
/*
synchronized(o)
{
//3.多条代码
if(num > 0)
{
try{Thread.sleep(10);}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"==="+num--);
}
}
*/
show();
}
}
public synchronized void show()
{
//3.多条代码
if(num > 0)
{
try{Thread.sleep(10);}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"==="+num--);
}
}
}
结果:

2.2、静态同步函数
代码:
class Ticket implements Runnable
{
//2.共享数据
private static int num = 100;
//同步锁:对象
//private Object o=new Object();
public void run()
{
while(true)
{
/*
synchronized(o)
{
//3.多条代码
if(num > 0)
{
try{Thread.sleep(10);}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"==="+num--);
}
}
*/
show();
}
}
public static synchronized void show()
{
//3.多条代码
if(num > 0)
{
try{Thread.sleep(10);}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"==="+num--);
}
}
}
结果:

同步的弊端:效率低,因为同步外的线程都会判断同步锁
Java学习之多线程(线程安全问题及线程同步)的更多相关文章
- Java学习笔记-多线程-创建线程的方式
创建线程 创建线程的方式: 继承java.lang.Thread 实现java.lang.Runnable接口 所有的线程对象都是Thead及其子类的实例 每个线程完成一定的任务,其实就是一段顺序执行 ...
- 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁
什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...
- 2019/3/7 Java学习之多线程(基础)
Java学习之多线程 讲到线程,就必须要懂得进程,进程是相当于一个程序的开始到结束,而线程是依赖于进程的,没有进程,就没有线程.线程也分主线程和子线程,当在主线程开启子线程时,主线程结束,而子线程还可 ...
- java学习笔记 --- 多线程(线程安全问题——同步代码块)
1.导致出现安全问题的原因: A:是否是多线程环境 B:是否有共享数据 C:是否有多条语句操作共享数据 2.解决线程安全问题方法: 同步代码块: synchronized(对象){ 需要同步的代码; ...
- 0041 Java学习笔记-多线程-线程池、ForkJoinPool、ThreadLocal
什么是线程池 创建线程,因为涉及到跟操作系统交互,比较耗费资源.如果要创建大量的线程,而每个线程的生存期又很短,这时候就应该使用线程池了,就像数据库的连接池一样,预先开启一定数量的线程,有任务了就将任 ...
- 0040 Java学习笔记-多线程-线程run()方法中的异常
run()与异常 不管是Threade还是Runnable的run()方法都没有定义抛出异常,也就是说一条线程内部发生的checked异常,必须也只能在内部用try-catch处理掉,不能往外抛,因为 ...
- 0039 Java学习笔记-多线程-线程控制、线程组
join线程 假如A线程要B线程去完成一项任务,在B线程完成返回之前,不进行下一步执行,那么就可以调用B线程的join()方法 join()方法的重载: join():等待不限时间 join(long ...
- 0038 Java学习笔记-多线程-传统线程间通信、Condition、阻塞队列、《疯狂Java讲义 第三版》进程间通信示例代码存在的一个问题
调用同步锁的wait().notify().notifyAll()进行线程通信 看这个经典的存取款问题,要求两个线程存款,两个线程取款,账户里有余额的时候只能取款,没余额的时候只能存款,存取款金额相同 ...
- 0036 Java学习笔记-多线程-创建线程的三种方式
创建线程 创建线程的三种方式: 继承java.lang.Thread 实现java.lang.Runnable接口 实现java.util.concurrent.Callable接口 所有的线程对象都 ...
随机推荐
- spring-第七篇之深入理解容器中的bean
1.抽象bean与子bean 用于指定配置模板. 2.容器中的工厂bean 这种工厂bean必须实现FactoryBean接口,通过spring容器getBean()方法获取它时,容器返回的不是Fac ...
- 组件化框架设计之AOP&IOC(四)
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 本篇文章将从以下两个方面来介绍组件化框架设计: [AOP(面向切 ...
- [Python] 迭代器是什么?你每天在用的for循环都依赖它!
从循环说起 顺序,分支,循环是编程语言的三大逻辑结构,在Python中都得到了支持,而Python更是为循环结构提供了非常便利的语法:for ... in ... 刚从C语言转入Python的同学可能 ...
- P1021 邮票面值设计(dfs+背包dp)
P1021 邮票面值设计 题目传送门 题意: 给定一个信封,最多只允许粘贴N张邮票,计算在给定K(N+K≤15N+K≤15)种邮票的情况下 (假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大 ...
- BFS+打印路径
题目是给你起点sx,和终点gx:牛在起点可以进行下面两个操作: 步行:John花一分钟由任意点X移动到点X-1或点X+1. 瞬移:John花一分钟由任意点X移动到点2*X. 你要输出最短步数及打印路径 ...
- 问题处理——"无法导航到插入符号下的符号"
最近编码时经常发现"转到定义"功能没法用了,代码一片灰.刚开始时重新编译一下项目或重启一下VS就恢复了,但到后面这两种方法都不管用了. 偶然下发现解决方案中很多项目的引用都出现了黄 ...
- SQL server2000 创建表单的方法(已实践检验)
我的系统是win7旗舰版的,在安装完SQL server2000之后,单击表,右键-新建表时,系统要么弹出:MMC检测到此管理单元发生一个错误.要么直接弹出microsoft sql server 2 ...
- Cheatsheet: 2019 07.01 ~ 09.30
Other Intro Guide to Dockerfile Best Practices QuickJS Javascript Engine Questions for a new technol ...
- mysql sqlyog提示2058错误或者用Navicat连接本机Docker的Mysql 和一些问题的解决方案
1. 下载Mysql的Docker镜像: [plain] view plain copy$ docker search mysql (搜索mysql镜像) $ docker pull mysql ( ...
- Swagger添加文件上传测试
先上对比图 图一无法选择文件,图二可以选择文件 图一 图二 添加过滤器 public class SwaggerFileUploadFilter : IOperationFilter { /// &l ...