菜鸡的Java笔记 - java 线程的同步与死锁 (同步 synchronization,死锁 deadlock)
线程的同步与死锁 (同步 synchronization,死锁 deadlock)
多线程的操作方法
1.线程同步的产生与解决
2.死锁的问题
同步问题的的引出
如果要想进行同步的操作,那么很明显就是多个线程需要访问同一资源
范例:以卖票程序为例
package cn.mysterious.study3;
class MyThread implements Runnable{
private int ticket = 5;
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 10; i++) {
if (this.ticket > 0) {
System.out.println(Thread.currentThread().getName() + ",ticket = "+this.ticket --);
}
}
}
}
public class StudyThread {
public static void main(String[] args) throws Exception {
MyThread mt = new MyThread();
Thread t1 = new Thread(mt,"票贩子A");
Thread t2 = new Thread(mt,"票贩子B");
Thread t3 = new Thread(mt,"票贩子C");
t1.start();
t2.start();
t3.start();
}
}
于是下面开始挖掘本程序所存在的问题
范例:观察程序的问题
package cn.mysterious.study3;
class MyThread implements Runnable{
private int ticket = 5;
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 10; i++) {
if (this.ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ",ticket = "+this.ticket --);
}
}
}
}
public class StudyThread {
public static void main(String[] args) throws Exception {
MyThread mt = new MyThread();
Thread t1 = new Thread(mt,"票贩子A");
Thread t2 = new Thread(mt,"票贩子B");
Thread t3 = new Thread(mt,"票贩子C");
t1.start();
t2.start();
t3.start();
}
}
// 结果出现了负数
bane这样的操作就属于线程的不同步的操作,所以发现多个线程操作时必须要考虑到资源同步的问题
实现同步操作
整个代码之中发现有一个逻辑上的流程错误了,以上的程序中,将判断是否有票,延迟,卖票分为了三个部分
那么实际上每个线程如果要执行卖票的话,其他线程应该等待当前线程执行完毕后才可以进入
如果要想在若干个代码上实现锁这个概念,那么就需要通过使用同步代码块或者同步方法来解决
1.同步代码块
使用 synchronized 关键字定义的代码块就称为同步代码块,但是在进行同步的时候需要设置有一个同步对象,那么往往可以使用 this 同步当前对象
package cn.mysterious.study3;
class MyThread implements Runnable{
private int ticket = 500;
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 1000; i++) {
synchronized (this) {
if (this.ticket > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ",ticket = "+this.ticket --);
}
}
}
}
}
public class StudyThread {
public static void main(String[] args) throws Exception {
MyThread mt = new MyThread();
Thread t1 = new Thread(mt,"票贩子A");
Thread t2 = new Thread(mt,"票贩子B");
Thread t3 = new Thread(mt,"票贩子C");
t1.start();
t2.start();
t3.start();
}
}
加入同步之后整个代码执行的速度已经变慢了,而已不像美誉同步的时候那样多个线程一起进入到方法之中
异步的执行速度要快于同步的执行速度,但是异步的操作属于非线程安全的操作,而同步的操作属于线程的安全操作
2.同步方法
但是对于同步操作,除了用于代码块定义之外,也可以在方法上定义同步操作
package cn.mysterious.study3;
class MyThread implements Runnable{
private int ticket = 500;
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 1000; i++) {
sale();
}
}
public synchronized void sale(){ // 卖票
if (this.ticket > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ",ticket = "+this.ticket --);
}
}
}
public class StudyThread {
public static void main(String[] args) throws Exception {
MyThread mt = new MyThread();
Thread t1 = new Thread(mt,"票贩子A");
Thread t2 = new Thread(mt,"票贩子B");
Thread t3 = new Thread(mt,"票贩子C");
t1.start();
t2.start();
t3.start();
}
}
在多个线程访问同一资源时一定要考虑到数据的同步问题,同步就使用 synchronized 关键字
死锁分析(了解)
很明显,死锁是一种不确定的状态,对于死锁的操作应该出现的越少越好,下面的代码只是一个死锁的演示,代码不做任何实际的意义
package cn.mysterious.study3;
class Kidnapper{ // 绑匪
public synchronized void say(Landlord dz){
System.out.println(" 绑匪说:给我3亿美金,放了你儿子!");
dz.get();
}
public synchronized void get(){
System.out.println("绑匪得到钱");
}
}
class Landlord{ // 地主
public synchronized void say(Kidnapper bf){
System.out.println(" 地主说:放了我儿子,再给钱!");
bf.get();
}
public synchronized void get(){
System.out.println("救回.....");
}
}
public class StudyThread implements Runnable{
private Kidnapper bf = new Kidnapper();
private Landlord dz = new Landlord();
public StudyThread (){
new Thread(this).start();
dz.say(bf);
}
public static void main(String[] args) throws Exception {
new StudyThread();
}
@Override
public void run() {
// TODO Auto-generated method stub
bf.say(dz);
}
}
面试题:请问多个线程访问同一资源时可能带来什么问题?以及会产生什么样的附加问题?
多个线程访同一资源时必须考虑同步问题,可以使用 synchronized 定义同步代码块或者是同步方法
程序中如果出现过多的同步那么就将产生死锁
总结
如果看见 synchronized 声明的方法,一定有爱记住这是一个同步方法,属于线程安全的操作
菜鸡的Java笔记 - java 线程的同步与死锁 (同步 synchronization,死锁 deadlock)的更多相关文章
- Java 笔记 —— java 和 javac
Java 笔记 -- java 和 javac h2{ color: #4ABCDE; } a{ text-decoration: none !important; } a:hover{ color: ...
- java笔记--使用线程池优化多线程编程
使用线程池优化多线程编程 认识线程池 在Java中,所有的对象都是需要通过new操作符来创建的,如果创建大量短生命周期的对象,将会使得整个程序的性能非常的低下.这种时候就需要用到了池的技术,比如数据库 ...
- java 笔记(5) —— 线程,yield,join
一.线程各个状态与转换: 新建状态:用new语句创建的线程对象处于新建状态,此时它和其它的java对象一样,仅仅在堆中被分配了内存 .就绪状态:当一个线程创建了以后,其他的线程调用了它的start() ...
- java笔记--守护线程的应用
守护线程的应用 Java中的线程可以分为两类,即用户线程和守护线程.用户线程是为了完成任务,而守护线程是为其他线程服务 --如果朋友您想转载本文章请注明转载地址"http://www.cnb ...
- java笔记--关于线程死锁
关于线程死锁 什么是死锁: 在编写多线程的时候,必须要注意资源的使用问题,如果两个或多个线程分别拥有不同的资源, 而同时又需要对方释放资源才能继续运行时,就会发生死锁. 简单来说:死锁就是当一个或多个 ...
- 菜鸡的Java笔记 - java 线程常用操作方法
线程常用操作方法 线程的命名操作,线程的休眠,线程的优先级 线程的所有操作方法几乎都在 Thread 类中定义好了 线程的命名和取得 ...
- 菜鸡的Java笔记 java基础类库 BaseClassLibrary
java基础类库 BaseClassLibrary StringBuffer 类的特点 StringBuffer,StringBuilder,String 类之间的关系 ...
- 菜鸡的Java笔记 - java 断言
断言:assert (了解) 所谓的断言指的是在程序编写的过程之中,确定代码执行到某行之后数据一定是某个期待的内容 范例:观察断言 public class Abnorma ...
- 菜鸡的Java笔记 - java 正则表达式
正则表达式 RegularExpression 了解正则表达式的好处 正则表达式的基础语法 正则表达式的具体操作 content (内容 ...
随机推荐
- Decorator装饰器模式个人理解
对于装饰器模式,其主要是为了:在不改变本体特征的情况下,对其进行包装.装饰,目的是为了补充.扩展.增强其功能. 有三个原则: 不能改变本体的特征 要对本体的功能进行扩展 装饰器脱离了本体则没有任何含义 ...
- 小记SpringMVC与SpringBoot 的controller的返回json数据的不同
近期由于项目的改动变更,在使用springmvc和springboot测试的时候发现一个有趣的现象 1.springmvc的controller使用@ResponseBody返回的仅仅是json格式的 ...
- 极简SpringBoot指南-Chapter00-学习SpringBoot前的基本知识
仓库地址 w4ngzhen/springboot-simple-guide: This is a project that guides SpringBoot users to get started ...
- oracle扩展表空间
1. 查看表空间的名字及文件所在的位置 select tablespace_name, file_id, file_name, round(bytes / (1024 * 1024), 0) tot ...
- 【UE4 设计模式】策略模式 Strategy Pattern
概述 描述 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法的变化不会影响到使用算法的客户. 套路 Context(环境类) 负责使用算法策略,其中维持了一 ...
- JVM:内存溢出OOM
JVM:内存溢出OOM 本笔记是根据bilibili上 尚硅谷 的课程 Java大厂面试题第二季 而做的笔记 经典错误 JVM 中常见的两个 OOM 错误 StackoverflowError:栈溢出 ...
- Uniapp云打包生成apk下载链接
使用uni[]()app云打包生成安装包下载链接 manifest.json 中配置自动获取appid manifest.json中配置app 图标 按教程生成.keystore证书 使用云打包生成安 ...
- [火星补锅] 水题大战Vol.2 T1 && luogu P1904 天际线 题解 (线段树)
前言: 当时考场上并没有想出来...后来也是看了题解才明白 解析: 大家(除了我)都知道,奇点和偶点会成对出现,而出现的前提就是建筑的高度突然发生变化.(这个性质挺重要的,我之前没看出来) 所以就可以 ...
- sort方法和自定义比较器的写法
摘要 在做一些算法题时常常会需要对数组.自定义对象.集合进行排序. 在java中对数组排序提供了Arrays.sort()方法,对集合排序提供Collections.sort()方法.对自定义对象排序 ...
- 嵌入式开发板nfs挂载
板子要开始调试了,第一个头大的问题就是调试过程中更新的文件怎么更新到板子上,以前用sd卡拷贝来来回回太浪费时间了,adb也需要接线各种连接操作. 现在板子有wifi可用,是时候把nfs共享搭起来了. ...