线程安全---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.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...
随机推荐
- 逆向破解之160个CrackMe —— 010-011
CrackMe —— 010 160 CrackMe 是比较适合新手学习逆向破解的CrackMe的一个集合一共160个待逆向破解的程序 CrackMe:它们都是一些公开给别人尝试破解的小程序,制作 c ...
- OpenGL入门(一):使用GLFW创建简单的窗口
如果使用QT,那么创建一个OpenGL渲染窗口其实很容易,不过出于初学的角度,使用GLFW库来创建新窗口. 1. 下载并配置GLFW GLFW是一个专门针对OpenGL的C语言库,它提供了一些渲染物体 ...
- 201871010105-曹玉中《面向对象程序设计(java)》第十四周学习总结
201871010105-曹玉中<面向对象程序设计(java)>第十四周学习总结 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ ...
- 201871010108-高文利《面向对象程序设计(java)》第八周学习总结
项目 内容 这个作业属于哪个课程 <任课教师博客主页链接> https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 <作业链接地址> ht ...
- vs在matlab生成的dll中,load treebigger错误
提示的错误:Warning: Variable 'model' originally saved as a TreeBagger cannot be instantiated as an object ...
- <Graph> 133 399 223
133. Clone Graph 我们也可以使用 BFS 来遍历图,使用队列 queue 进行辅助,还是需要一个 HashMap 来建立原图结点和克隆结点之间的映射.先克隆当前结点,然后建立映射,并加 ...
- 使用logstash同步mysql数据库信息到ElasticSearch
本文介绍如何使用logstash同步mysql数据库信息到ElasticSearch. 1.准备工作 1.1 安装JDK 网上文章比较多,可以参考:https://www.dalaoyang.cn/a ...
- Postman测试后台使用@RequestBody接收参数的坑
问题原因:我在使用PostMan测试接口时发现数据传递不过来,是因为请求体定义为JSON数据,自动就传递不过来,虽然问题简单,但由于之前这个用的较少,所以就忽略了这点. 解决问题链接:https:// ...
- 【阿里云IoT+YF3300】2.阿里云IoT云端通信Alink协议介绍
如果单单只有MQTT协议,也许很难支撑起阿里这个IoT大厦.Alink协议的出现,不仅仅是数据从传感端搬到云端,它就如基因图谱,它勾画了一个大厦的骨架,有了它,才有了IoT Studio,才有了大数据 ...
- jenkins 更新插件使用代理
方法一: 管理插件页面配置如下: 这个 URL 改成http://mirror.xmission.com/jenkins/updates/update-center.json 或https://mir ...