线程安全---Day23
最近忙着备考大学四年最后的两科,昨天刚考完大学所有的考试,但是大学专业是机械,但是自己热衷于IT行业,想往IT行业走,希望毕业后能成功进入到IT行业,只希望毕业能找到一份Java开发工程师的工作,这样我才能专研和学习到更高深的技术.希望在毕业前能学到一点Java的精髓,让我可以成功进入到IT行业,加油~
线程问题:
package demosummary.threadsafety; public class Ticket implements Runnable{
//定义票数
private int ticket = 100;
/**
* 执行卖票方法
*/
@Override
public void run() {
//卖票窗口永久开启
while (true) {
//判断票是否卖完
if (ticket > 0) {
try {
//三秒卖一张票
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String name = Thread.currentThread().getName();
System.out.println(name+"正在卖:"+ticket--);
}
}
}
} package demosummary.threadsafety; public class TicketTest {
public static void main(String[] args) {
//创建线程任务对象
Ticket ticket = new Ticket();
//创建三个窗口对象
Thread t1 = new Thread(ticket, "窗口1");
Thread t2 = new Thread(ticket, "窗口2");
Thread t3 = new Thread(ticket, "窗口3");
//启用窗口来卖票
t1.start();
t2.start();
t3.start();
}
/**
* 执行结果
* 窗口2正在卖:79
* 窗口3正在卖:79
* 窗口1正在卖:-1
* 出现重复卖同一张票和负票,在现实中是不允许出现的
*/
}
注意:执行结果出现两种问题
1.出现不同窗口卖同一张票,把票卖了两次
2.出现卖不存在的票
注意:这两种问题称为线程不安全
线程安全问题都是由全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无写 操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步, 否则的话就可能影响线程安全
线程同步
当我们使用多个线程访问同一资源的时候,且多个线程中对资源有写的操作,就容易出现线程安全问题。要解决上述多线程并发访问一个资源的安全性问题:也就是解决重复票与不存在票问题,Java中提供了同步机制 (synchronized)来解决
方法:
1. 同步代码块
2. 同步方法
3. 锁机制
同步代码块
同步代码块: synchronized 关键字可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问
格式:
synchronized(同步锁){
需要同步操作的代码
}
同步锁:对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁
1. 锁对象 可以是任意类型。
2. 多个线程对象 要使用同一把锁
同步锁是谁?
对于非static方法,同步锁就是this。
对于static方法,我们使用当前方法所在类的字节码对象(类名.class)。
注意:在任何时候,最多允许一个线程拥有同步锁,谁拿到锁就进入代码块,其他的线程只能在外等着 (BLOCKED)
package demosummary.threadsafety; public class Ticket02 implements Runnable {
//定义票数
private int ticket = 100; Object lock = new Object();
/**
* 执行卖票方法
*/
@Override public void run() {
//卖票窗口永久开启
while (true) {
synchronized (lock) {
//判断票是否卖完
if (ticket > 0) {
try {
//三秒卖一张票
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String name = Thread.currentThread().getName();
System.out.println(name + "正在卖:" + ticket--);
}
}
}
}
} package demosummary.threadsafety; public class TicketTest02 {
public static void main(String[] args) {
//创建线程任务对象
Ticket02 ticket = new Ticket02();
//创建三个窗口对象
Thread t1 = new Thread(ticket, "窗口1");
Thread t2 = new Thread(ticket, "窗口2");
Thread t3 = new Thread(ticket, "窗口3");
//启用窗口来卖票
t1.start();
t2.start();
t3.start();
}
}
使用了同步代码块可以解决线程安全问题
同步方法
同步方法:使用synchronized修饰的方法,就叫做同步方法,保证A线程执行该方法的时候,其他线程只能在方法外等着。
格式:
public synchronized void method(){
可能会产生线程安全问题的代码
}
package demosummary.threadsafety; public class Ticket03 implements Runnable {
private int ticket = 100; /**
* 执行卖票方法
*/
@Override
public void run() {
//卖票窗口永久开启
while (true) {
sellTicket();
}
} private synchronized void sellTicket() {
//判断票是否卖完
if (ticket > 0) {
try {
//三秒卖一张票
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//获取线程名称
String name = Thread.currentThread().getName();
System.out.println(name + "正在卖:" + ticket--);
}
}
} package demosummary.threadsafety; public class TicketTest03 {
public static void main(String[] args) {
//创建线程任务对象
Ticket03 ticket = new Ticket03();
//创建三个窗口对象
Thread t1 = new Thread(ticket, "窗口1");
Thread t2 = new Thread(ticket, "窗口2");
Thread t3 = new Thread(ticket, "窗口3");
//启用窗口来卖票
t1.start();
t2.start();
t3.start();
}
}
Lock锁
java.util.concurrent.locks.Lock 机制提供了比synchronized代码块和synchronized方法更广泛的锁定操作, 同步代码块/同步方法具有的功能Lock都有,除此之外更强大,更体现面向对象
Lock锁也称同步锁,加锁与释放锁方法化了,如下
public void lock() :加同步锁。
public void unlock() :释放同步
package demosummary.threadsafety; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class Ticket04 implements Runnable {
//定义票数
private int ticket = 100; //创建锁对象
Lock lock = new ReentrantLock();
/**
* 执行卖票方法
*/
@Override
public void run() {
//卖票窗口永久开启
while (true) {
//给线程加锁
lock.lock();
//判断是否邮票可卖
if (ticket > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//获取线程当前名称
String name = Thread.currentThread().getName();
System.out.println(name+"正在卖"+ticket--);
}
//释放线程锁
lock.unlock();
}
}
} package demosummary.threadsafety; public class TicketTest04 {
public static void main(String[] args) {
//创建线程任务对象
Ticket04 ticket = new Ticket04();
//创建三个窗口对象
Thread t1 = new Thread(ticket, "窗口1");
Thread t2 = new Thread(ticket, "窗口2");
Thread t3 = new Thread(ticket, "窗口3");
//启用窗口来卖票
t1.start();
t2.start();
t3.start();
}
}
线程安全---Day23的更多相关文章
- 老男孩python学习自修第二十三天【多线程】
1. 线程的创建与运行 #!/usr/bin/env python # _*_ coding:UTF-8 _*_ from threading import Thread def foo(param1 ...
- 黑马程序员_Java基础视频-深入浅出精华版--视频列表
\day01\avi\01.01_计算机基础(计算机概述).avi; \day01\avi\01.02_计算机基础(计算机硬件和软件概述).avi; \day01\avi\01.03_计算机基础(软件 ...
- 课程2:《黑马程序员_Java基础视频-深入浅出精华版》-视频列表-
\day01\avi\01.01_计算机基础(计算机概述).avi; \day01\avi\01.02_计算机基础(计算机硬件和软件概述).avi; \day01\avi\01.03_计算机基础(软件 ...
- Pyhton学习——Day23
#re模块方法:findall search#findall:返回所有满足匹配条件的数值,放在列表里#search : #函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象 ...
- javasE--基础部分--线程
Day23 本单元目标 一.线程的相关概念 二.线程的创建和启动★ 三.线程的停止 四.线程的常用方法 五.线程的生命周期★ 六.线程的同步 七.线程的通信 八.线程的创建方式三 九.线程的创建方 ...
- Java第二十四天,线程安全
线程安全 1.定义 多线程访问共享数据,会产生线程安全问题. 2.代码模拟 卖票Ticked类: package com.lanyue.day22; public class Person { pub ...
- [ 高并发]Java高并发编程系列第二篇--线程同步
高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...
- [高并发]Java高并发编程系列开山篇--线程实现
Java是最早开始有并发的语言之一,再过去传统多任务的模式下,人们发现很难解决一些更为复杂的问题,这个时候我们就有了并发. 引用 多线程比多任务更加有挑战.多线程是在同一个程序内部并行执行,因此会对相 ...
- 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)
前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...
随机推荐
- ZAP 代理 Chrome 系统 win10
ZAP 代理原理 如下浏览器,拿Chrome为例,Chrome发出的请求都会先经过 ZAP, 然后再由 ZAP 发往服务器.如下图: Chrome 设置 1. Chrome设置只需要在地址栏输入 ch ...
- hydra使用,实例介绍
hydra 是一个网络帐号破解工具,支持多种协议.其作者是van Hauser,David Maciejak与其共同维护.hydra在所有支持GCC的平台能很好的编译,包括Linux,所有版本的BSD ...
- Java命令行传参
目的: 在运行一个程序时候再传递给它消息,这就需要传递命令参数给main()函数实现:即main()方法可以传递数据 例: public class demo{ public static void ...
- luoguP2882Face The Right Way
https://www.luogu.org/problem/P2882 题意 你有n头牛,每头牛有个朝向,你每次可以选择连续k头牛翻转,求k为多少时可以用最少的步骤将所有牛朝向变为正向 n≤5000 ...
- 201871010108-高文利《面向对象程序设计(java)》第七周学习总结
项目 内容 这个作业属于哪个课程 <任课教师博客主页链接> https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 <作业链接地址> ht ...
- 201871020225-牟星源《面向对象程序设计(java)》第十二周学习总结
201871020225-牟星源<面向对象程序设计(java)>第十二周学习总结 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ ...
- C#基础操作符详解(下)
书接上文的基本操作符,下文介绍的是其他操作符: 4.2一元操作符: 只要有一个操作数跟在它后面就可以构成表达式,也叫单目操作符. ①&x和*x操作符(很少见有印象即可): 这两个操作符同样也需 ...
- JAVA大数的一些操作
参考: https://www.cnblogs.com/tonyyy/p/10433460.html https://www.cnblogs.com/wkfvawl/p/9377441.html (d ...
- http协议里定义的四种常见数据的post方法
原文 https://blog.csdn.net/charlene0824/article/details/51199292 关于http协议里定义的四种常见数据的post方法,分别是: applic ...
- 【转】spring的AOP原理,使用场景是什么?
什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入 ...