概念:Java同步和异步,阻塞和非阻塞

1、线程的同步产生的原因

没有同步的情况

class MyThread1 implements Runnable
{
private int ticket=5;
@Override
public void run() {
for(int x =0;x<20;x++)
{ if(ticket>0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"卖票:"+this.ticket--);
}
}
} }
public class Test {
public static void main(String[] args) {
MyThread1 mt = new MyThread1();
new Thread(mt,"票贩子A").start();
new Thread(mt,"票贩子B").start();
new Thread(mt,"票贩子C").start();
new Thread(mt,"票贩子D").start();
}
}
票贩子C卖票:5
票贩子D卖票:5
票贩子B卖票:4
票贩子A卖票:3
票贩子D卖票:2
票贩子C卖票:1
票贩子A卖票:-1
票贩子B卖票:0
票贩子D卖票:-2

可以看到又相同的票被卖了,还出现了负数票的情况。

2、线程的同步处理操作

实现同步的关键字synchronized,可以通过两种方式使用

  • 一种是同步代码块
  • 另外一种是同步方法

    在Java里面有四种代码块:普通代码块、构造块、静态块、同步块

使用同步代码块实现同步

class MyThread1 implements Runnable
{
private int ticket=10;
@Override
public void run() { for(int x =0;x<20;x++)
{
synchronized(this){
if(ticket>0) {
System.out.println(Thread.currentThread().getName()+"卖票:"+this.ticket--);
}
}
}
} }
public class SynchronizedThread {
public static void main(String[] args) {
MyThread1 mt = new MyThread1();
new Thread(mt,"票贩子A").start();
new Thread(mt,"票贩子B").start();
new Thread(mt,"票贩子C").start();
new Thread(mt,"票贩子D").start();
}
}
票贩子A卖票:10
票贩子D卖票:9
票贩子C卖票:8
票贩子B卖票:7
票贩子C卖票:6
票贩子C卖票:5
票贩子C卖票:4
票贩子D卖票:3
票贩子A卖票:2
票贩子D卖票:1

调用同步方法实现同步

class MyThread1 implements Runnable
{
private int ticket=10;
@Override
public void run() {
for(int x =0;x<20;x++)
{
this.sale();
}
}
public synchronized void sale()
{
if(ticket>0) {
System.out.println(Thread.currentThread().getName()+"卖票:"+this.ticket--);
}
} }
public class SynchronizedThread {
public static void main(String[] args) {
MyThread1 mt = new MyThread1();
new Thread(mt,"票贩子A").start();
new Thread(mt,"票贩子B").start();
new Thread(mt,"票贩子C").start();
new Thread(mt,"票贩子D").start();
}
}

3、线程的死锁情况

Java 实例 - 死锁及解决方法

public class DeadLock {
public static void main(String[] args) { DeadService deadService = new DeadService(); new Thread(new DeadRunnable(deadService),"a").start();
new Thread(new DeadRunnable(deadService),"b").start();
}
} class DeadRunnable implements Runnable { DeadService deadService; public DeadRunnable(DeadService deadService) {
this.deadService = deadService;
} @Override
public void run() {
String name = Thread.currentThread().getName();
if ("a".equals(name)) {
deadService.methodA();
} else if ("b".equals(name)) {
deadService.methodB();
}
}
} class DeadService { final Object objectA = new Object();
final Object objectB = new Object(); /**
* 互斥条件:objectA、objectB对象只能同一时间被一个方法锁住
* 请求与保持条件:methodA()方法锁objectA对象的时候未释放又申请锁objectB对象,methodB()方法锁objectB对象的时候未释放又申请锁objectA对象
* 不可抢占条件: 锁objectA,锁objectB未释放前不能再被其他方法剥夺锁
* 循环等待条件:methodA()等待objectB对象锁的释放、methodB()等待objectA对象锁的释放
*/
public void methodA() {
synchronized (objectA) {
System.out.println("methodA() start.." + Thread.currentThread().getName());
ThreadUtil.sleep(3000);
synchronized (objectB) {
System.out.println("methodA() end.." + Thread.currentThread().getName());
}
}
} public void methodB() {
synchronized (objectB) {
System.out.println("methodB() start.." + Thread.currentThread().getName());
ThreadUtil.sleep(3000);
synchronized (objectA) {
System.out.println("methodB() end.." + Thread.currentThread().getName());
}
}
}
}

运行结果:

methodA() start..a
methodB() start..b

发现程序卡在这里,系统出现死锁。

死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。

java 死锁产生的四个必要条件:

1、互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用

2、不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。

3、请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。

4、循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。

解决方法:

  • 用信号量去控制死锁。
  • 调整申请锁的范围
  • 调整申请锁的顺序

避免死锁:银行家算法。

排查死锁的方式:

  1. Java 进程的信息
E:\code\IdeaProjects\learn-java>jps
8096 Jps
13060
18868 DeadLock
17500 Launcher

jps 是 Java Virtual Machine Process Status Tool(Java 虚拟机进程状态工具)的缩写。它是 JDK 提供的一个命令行工具,用于列出当前系统上正在运行的 Java 进程的信息,包括 Java 进程的进程 ID(PID)和主类的名称

  1. 打印死锁进程的堆栈信息
E:\code\IdeaProjects\learn-java>jstack -l 18868
……
……
……
Java stack information for the threads listed above:
===================================================
"a":
at com.zjw._02.synstatic.DeadService.methodA(DeadLock.java:71)
- waiting to lock <0x0000000622ed3648> (a java.lang.Object)
- locked <0x0000000622ed3638> (a java.lang.Object)
at com.zjw._02.synstatic.DeadRunnable.run(DeadLock.java:48)
at java.lang.Thread.run(java.base@17.0.10/Thread.java:840)
at java.lang.Thread.run(java.base@17.0.10/Thread.java:840)
"b":
at com.zjw._02.synstatic.DeadService.methodB(DeadLock.java:81)
- waiting to lock <0x0000000622ed3638> (a java.lang.Object)
- locked <0x0000000622ed3648> (a java.lang.Object)
at com.zjw._02.synstatic.DeadRunnable.run(DeadLock.java:50)
at java.lang.Thread.run(java.base@17.0.10/Thread.java:840) Found 1 deadlock.

通过堆栈信息我们可以查看死锁发生的位置。

请解释多个线程访问统一资源时需要考虑哪些情况?有可能带来哪些后果?

多个线程访问同一资源时要考虑到线程间的同步问题,可以使用同步代码或同步方法解决;

同步代码块:synchronized(锁定对象){代码}

同步方法: public synchronized 返回值 方法名称(){代码}

但是过多的使用同步,有可能造成死锁。

Java 线程的同步与死锁的更多相关文章

  1. 菜鸡的Java笔记 - java 线程的同步与死锁 (同步 synchronization,死锁 deadlock)

    线程的同步与死锁 (同步 synchronization,死锁 deadlock)        多线程的操作方法            1.线程同步的产生与解决        2.死锁的问题     ...

  2. 进阶Java编程(3)线程的同步与死锁

    线程的同步与死锁 1,同步问题引出 在多线程的处理之中,可以利用Runnable描述多个线程操作的资源,而Thread描述每一个线程对象,对于当多个线程访问统一资源的时候如果处理不当就会产生数据的错误 ...

  3. Java多线程编程(同步、死锁、生产消费者问题)

    Java多线程编程(同步.死锁.生产消费): 关于线程同步以及死锁问题: 线程同步概念:是指若干个线程对象并行进行资源的访问时实现的资源处理保护操作: 线程死锁概念:是指两个线程都在等待对方先完成,造 ...

  4. java 线程数据同步

    java 线程数据同步 由买票实例 //java线程实例 //线程数据同步 //卖票问题 //避免重复卖票 //线程 class xc1 implements Runnable{ //定义为静态,可以 ...

  5. Java 线程与同步的性能优化

    本文探讨的主题是,如何挖掘出Java线程和同步设施的最大性能. 1.线程池与ThreadPoolExecutor 1)线程池与ThreadPoolExecutor 线程池的实现可能有所不同,但基本概念 ...

  6. java多线程(同步与死锁问题,生产者与消费者问题)

    首先我们来看同步与死锁问题: 所谓死锁,就是A拥有banana.B拥有apple. A对B说:你把apple给我.我就把banana给你. B对A说:你把banana给我,我就把apple给你. 可是 ...

  7. java多线程(同步和死锁,生产者和消费者问题)

    首先我们来看看同步与死锁: 所谓死锁.这是A有banana,B有apple. A至B说:你把apple对我来说,,我会banana给你. B至A说:你把banana对我来说,,我会apple给你. 可 ...

  8. Java线程:同步

    一 同步的概念 线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏. 例如:两个线程ThreadA.ThreadB都操作同一个对象Foo对象,并修改Foo对象上的数据. MyRunnab ...

  9. java 线程(六)死锁

    package cn.sasa.demo4; public class ThreadDemo { public static void main(String[] args){ DeadLockRun ...

  10. Java线程安全同步容器

    线程安全同步容器(使用 synchronized关键字) 1.ArrayList->Vector,Stack 2.HashMap->HashTable(key.value不能为null) ...

随机推荐

  1. 调研报告-基于 Iceberg 构建湖仓一体平台调研

    一.背景 我们使用 Iceberg 构建湖仓一体平台的初衷是希望解决业务方在使用 Hive 数仓时的一些痛点.主要包括以下几大方面: (1)现有的数据同步只支持全量同步,同步大表速度慢. (2)Hiv ...

  2. Maven配置多数据源

    一.配置文件 修改maven配置文件,用户目录下.m2文件夹中的setting.xml,内容如下 <?xml version="1.0" encoding="UTF ...

  3. What?废柴, 还在本地部署DeepSeek吗?Are you kidding?

    前言 DeepSeek推出更强大的推理模型DeepSeek R1后一发不可收拾,迅速火遍全球,用户暴增,但巨大的流量以及一些不可控因素,DeepSeek官网变得极不稳定,经常出现"网络繁忙& ...

  4. FANUC机器人M-16iB伺服马达维修参考措施

    随着工业自动化技术的不断发展,机器人已经广泛应用于各个领域.其中,发那科机器人以其卓越的性能和稳定性,成为了许多企业的首选.然而,伺服电机作为机器人核心部件之一,FANUC机械手维修保养至关重要. 一 ...

  5. 洋葱学园:开启高效学习之旅的宝藏 APP 40天会员5元到手价

    洋葱学园是一款在在线教育领域表现出色的教学 APP ,下面为您详细介绍它的特点以及推荐理由. 丰富的学科覆盖: 洋葱学园涵盖了从小学到高中的全学科课程,包括数学.语文.英语.物理.化学等.无论您处于哪 ...

  6. DW001 - 数据仓库理论知识

    数据仓库概念 数据仓库基本架构 数据集市概念 数据湖概念 数据仓库概念 数据仓库(Data Warehouse,DW)是一个面向主题的.集成的.非易失的.反映历史变化的.用来支持企业管理决策的数据集合 ...

  7. Zookeeper - Zookeeper启动失败,日志报错 Missing election port for server: 2

    Missing election port for server: 2 [整理日期]2023年6月1日 [基础环境]JDK 1.8.0_372.Zookeeper 3.4.5 [问题描述]进行部署分布 ...

  8. C# USB 摄像头 OpenCV 视频picBox呈现,抓拍图像保存呈现。没有注释版本。

    1.winform 应用程序,两个picturebox空间,一个用于视频呈现,一个用于抓拍呈现. 2.引用包OpenCvSharp4.OpenCvSharp4.Extensions.OpenCvSha ...

  9. minecraft mods descrip

    1. [Advanced Finders]矿物探测器 mod 显示玩家周围附近矿石的方向(指针显示水平面上可到达的矿石) 探测地下深部矿脉(箭头显示最近矿脉的方向(上/下)) 发现大型矿床时发出信号( ...

  10. 华为云windows server 2008 迁机遇到字符串问题

    问题 使用主机迁移服务迁移windows server 2008出现问题 2.按照教程安装Windows Agent(Python2)下载后,在源主机上运行agent-start.exe,输入ak后, ...