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接口 所有的线程对象都 ...
随机推荐
- No-sql之redis常用命令
转自:http://blog.csdn.net/nicewuranran/article/details/51793760 No-SQL之Redis 介绍 Redis是一种基于内存存储的key-val ...
- [Linux] 003 分区
1. 磁盘分区 使用分区编辑器再磁盘上划分几个逻辑部分 不用类的目录与文件可以存储进不同的分区 2. 分区类型 主分区 最多只能有 4 个 扩展分区 最多只能有 1 个 主分区加扩展分区最多为 4 个 ...
- python第一部分小结
1.python的种类 Cpython: ...
- ZOJ 2706 Thermal Death of the Universe
Thermal Death of the Universe Time Limit: 10 Seconds Memory Limi ...
- 2019 Multi-University Training Contest 1 - 1004 - Vacation - 二分 - 思维
http://acm.hdu.edu.cn/showproblem.php?pid=6581 一开始想了好几个假算法.但是启发了一下潘哥,假如时间知道的话就可以从头开始确定各个车的位置.那么直接 \( ...
- Codeforces Round #529 (Div. 3) E. Almost Regular Bracket Sequence (思维)
Codeforces Round #529 (Div. 3) 题目传送门 题意: 给你由左右括号组成的字符串,问你有多少处括号翻转过来是合法的序列 思路: 这么考虑: 如果是左括号 1)整个序列左括号 ...
- 阿里云ECS服务安装 nginx+php+MariaDB完整版
安装 Nginx想在 CentOS 系统上安装 Nginx ,你得先去添加一个资源库,像这样: vim /etc/yum.repos.d/nginx.repo使用 vim 命令去打开 /etc/yum ...
- SpringCloud-Eureka-服务注册是如何发起的
原文:https://xsxy007.github.io Spring Cloud环境下,服务提供者和消费者启动后都会将自身注册到Eureka 一.将服务注册到Eureka 一个SpringBoot应 ...
- XSLT学习(九)通过JavaScript转化xml
如果您的浏览器支持 XSLT,那么在浏览器中它可被用来将文档转换为 XHTML. JavaScript 解决方案 在前面的章节,我们已向您讲解如何使用 XSLT 将某个 XML 文档转换为 XHTML ...
- 云中沙箱学习笔记1-快速部署并使用MySQL数据库
1.1 背景知识 业务背景 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于Oracle旗下产品.MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面MyS ...