java线程安全 ,死锁以及线程状态的介绍与使用

news2024/11/26 17:28:29

线程安全

1.什么时候发生:当多个线程访问同一个资源时,导致了数据有问题

1.线程安全问题–>线程不安全的代码

public class MyTicket implements Runnable{
    //定义100张票
    int ticket = 100;

    @Override
    public void run() {
        while(true){
            if (ticket>0){
                System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"张票");
                ticket--;
            }
        }
    }
}

public class Test01 {
    public static void main(String[] args) {
        MyTicket myTicket = new MyTicket();

        Thread t1 = new Thread(myTicket, "赵四");
        Thread t2 = new Thread(myTicket, "刘能");
        Thread t3 = new Thread(myTicket, "广坤");

        t1.start();
        t2.start();
        t3.start();
    }
}
原因:CPU在多个线程之间做高速切换导致的

2.解决线程安全问题的第一种方式(使用同步代码块)

1.格式:
  synchronized(任意对象){
      线程可能出现不安全的代码
  }
2.任意对象:就是我们的锁对象
3.执行:
  一个线程拿到锁之后,会进入到同步代码块中执行,在此期间,其他线程拿不到锁,就进不去同步代码块,需要在同步代码块外面等待排队,需要等着执行的线程执行完毕,出了同步代码块,相当于释放锁了,等待的线程才能抢到锁,才能进入到同步代码块中执行
public class MyTicket implements Runnable{
    //定义100张票
    int ticket = 100;

    //任意new一个对象
    Object obj = new Object();

    @Override
    public void run() {
        while(true){
            try {
                Thread.sleep(100L);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            synchronized (obj){
                if (ticket>0){
                    System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"张票");
                    ticket--;
                }
            }

        }
    }
}
public class Test01 {
    public static void main(String[] args) {
        MyTicket myTicket = new MyTicket();

        Thread t1 = new Thread(myTicket, "赵四");
        Thread t2 = new Thread(myTicket, "刘能");
        Thread t3 = new Thread(myTicket, "广坤");

        t1.start();
        t2.start();
        t3.start();
    }
}

3.解决线程安全问题的第二种方式:同步方法

3.1.普通同步方法_非静态

1.格式:
  修饰符 synchronized 返回值类型 方法名(参数){
      方法体
      return 结果
  }
2.默认锁:this
public class MyTicket implements Runnable{
    //定义100张票
    int ticket = 100;

    @Override
    public void run() {
        while(true){
            try {
                Thread.sleep(100L);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
           //method01();
            method02();
        }
    }

   /* public synchronized void method01(){
        if (ticket>0){
            System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"张票");
            ticket--;
        }
    }*/
   public void method02(){
       synchronized(this){
           System.out.println(this+"..........");
           if (ticket>0){
               System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"张票");
               ticket--;
           }
       }

   }

}

public class Test01 {
    public static void main(String[] args) {
        MyTicket myTicket = new MyTicket();
        System.out.println(myTicket);

        Thread t1 = new Thread(myTicket, "赵四");
        Thread t2 = new Thread(myTicket, "刘能");
        Thread t3 = new Thread(myTicket, "广坤");

        t1.start();
        t2.start();
        t3.start();
    }
}

3.2.静态同步方法

1.格式:
  修饰符 static synchronized 返回值类型 方法名(参数){
      方法体
      return 结果
  }
2.默认锁:class对象
public class MyTicket implements Runnable{
    //定义100张票
    static int ticket = 100;

    @Override
    public void run() {
        while(true){
            try {
                Thread.sleep(100L);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
           //method01();
            method02();
        }
    }

    /*public static synchronized void method01(){
        if (ticket>0){
            System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"张票");
            ticket--;
        }
    }*/
   public static void method02(){
       synchronized(MyTicket.class){
           if (ticket>0){
               System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"张票");
               ticket--;
           }
       }

   }
}
public class Test01 {
    public static void main(String[] args) {
        MyTicket myTicket = new MyTicket();

        Thread t1 = new Thread(myTicket, "赵四");
        Thread t2 = new Thread(myTicket, "刘能");
        Thread t3 = new Thread(myTicket, "广坤");

        t1.start();
        t2.start();
        t3.start();
    }
}

死锁

1.死锁介绍(锁嵌套就有可能产生死锁)

指的是两个或者两个以上的线程在执行的过程中由于竞争同步锁而产生的一种阻塞现象;如果没有外力的作用,他们将无法继续执行下去,这种情况称之为死锁

根据上图所示:线程1正在持有锁1,但是线程1必须再拿到锁2,才能继续执行
而线程2正在持有锁2,但是线程2需要再拿到锁1,才能继续执行
此时两个线程处于互相等待的状态,就是死锁,在程序中的死锁将出现在同步代码块的嵌套中

2.死锁的分析

3.代码实现

public class LockA {
    public static LockA lockA = new LockA();
}

public class LockB {
    public static LockB lockB = new LockB();
}
public class DieLock implements Runnable{
    private boolean flag;

    public DieLock(boolean flag) {
        this.flag = flag;
    }

    @Override
    public void run() {
        if (flag){
            synchronized (LockA.lockA){
                System.out.println("if...lockA");
                synchronized (LockB.lockB){
                    System.out.println("if...lockB");
                }
            }
        }else{
            synchronized (LockB.lockB){
                System.out.println("else...lockB");
                synchronized (LockA.lockA){
                    System.out.println("else...lockA");
                }
            }
        }
    }
}

public class Test01 {
    public static void main(String[] args) {
        DieLock dieLock1 = new DieLock(true);
        DieLock dieLock2 = new DieLock(false);

        new Thread(dieLock1).start();
        new Thread(dieLock2).start();
    }
}


只需要知道死锁出现的原因即可(锁嵌套),以后尽量避免锁嵌套

线程状态

1.线程状态介绍

  当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。在线程的生命周期中,有几种状态呢?在APIjava.lang.Thread.State这个枚举中给出了六种线程状态:
  这里先列出各个线程状态发生的条件,下面将会对每种状态进行详细解析。
线程状态导致状态发生条件
NEW(新建)线程刚被创建,但是并未启动。还没调用start方法。
Runnable(可运行)线程可以在java虚拟机中运行的状态,可能正在运行自己代码,也可能没有,这取决于操作系统处理器。
Blocked(锁阻塞)当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有,则该线程进入Blocked状态;当该线程持有锁时,该线程将变成Runnable状态。
Waiting(无限等待)一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状态。进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能够唤醒。
Timed Waiting(计时等待)同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。这一状态将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep 、Object.wait。
Terminated(被终止)因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。或者调用过时方法stop()

2.线程状态图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1835062.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【PL理论】(31) 类型系统:静态分析 (Static Analysis) | 静态类型系统 | 什么是类型?

💭 写在前面:本章我们将进入类型系统的讲解,回顾一下之前我们整理的 F- 语言,然后介绍一下静态分析和静态类型系统。讨论程序员该如何处理一些 bug,有没有完美的静态分析器。 目录 0x00 回顾:F- 语言 0x…

Part 4.4 树形动态规划

树形动态规划,即在树上进行的动态规划。 因为树的递归性质,树形动态规划一般都是递归求解的。 没有上司的舞会 题目描述 某大学有 n n n 个职员,编号为 1 … n 1\ldots n 1…n。 他们之间有从属关系,也就是说他们的关系就像…

Sectigo OV通配符SSL证书多少钱?

在网络安全领域,SSL数字证书起着至关重要的作用,尤其是在保护网站和用户信息方面。而Sectigo OV通配符证书是一种常用的数字证书之一,它能够为同一域名下的多个子域名提供保护,还能够通过企业验证来增强安全性。那么,对…

对input输入框的正则限制

一、0-100的整数 正则&#xff1a; const inputRules ref([{required: false,trigger: "blur",validator: (rule, value, callback) > {const reg /^[0-9]$/; // 只允许整数if ((0 < value && value < 100 && reg.test(value)) ||valu…

如何打开azw/azw3文件?两个步骤解决

要打开AZW或AZW3格式的电子书&#xff0c;遵循以下步骤&#xff0c;无论你是Windows、Mac用户&#xff0c;还是使用移动设备&#xff0c;都可以轻松阅读这些亚马逊Kindle专用格式的电子书&#xff1a; 第一步&#xff1a;安装NeatReader&#xff1a; 访问NeatReader的官方网站或…

MySQl基础入门⑯【操作视图】完结

上一边文章内容 表准备 CREATE TABLE Students (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(100),email VARCHAR(255),major VARCHAR(100),score int,phone_number VARCHAR(20),entry_year INT,salary DECIMAL(10, 2) );数据准备 INSERT INTO Students (id, name, ema…

谷歌可穿戴设备与生成式AI模型PH-LLM:打造个性化健康监测与指导的新纪元

随着移动和可穿戴设备的普及&#xff0c;它们为个人健康监测提供了前所未有的机会&#xff0c;通过收集步数、心率变异性、睡眠持续时间等连续、精细和纵向数据&#xff0c;帮助用户实时跟踪自己的健康状况。这些数据不仅可以用于简单的监测&#xff0c;还可以结合生成式人工智…

什么是模型轻量化?如何自动进行模型轻量化?

轻量化是已经是3D可视化业界人所共知的一个概念&#xff0c;虽然至今没有任何严谨的学术或者理论定义&#xff0c;但是这个概念已经几乎成为了行业的标准。它的大意是说&#xff0c;一个适用用于浏览器端渲染的模型数据&#xff0c;包括几何数据和行业数据&#xff0c;必然可以…

数据库、中台、报表平台之间的关系

我最近在接触报表平台和中台&#xff0c;发现他们跟我平常用的数据库不是一个东西。然后&#xff0c;我开始了摸索他们的过程&#xff0c;终于&#xff0c;我在理清他们的关系以后&#xff0c;简单写一个入门级的区分。 数据库&#xff1a; 定义&#xff1a; 数据库是被长期存…

MySQL 下载及安装教程

MySQL是一款开源的关系数据库管理系统&#xff0c;被广泛应用于各种应用程序和网站的数据管理中。以下是下载和安装MySQL的详细步骤。 1. 访问MySQL官方网站 首先&#xff0c;打开你的浏览器&#xff0c;访问MySQL官方网站&#xff1a; MySQL官方网站: https://www.mysql.com …

同三维T80004EHU 高清HDMI/USB编码器

1路HDMI或1路USB输入&#xff0c;带1路3.5音频输入&#xff0c;高清1080P60 来百度APP畅享高清图片 产品简介&#xff1a; 同三维T80004EHU 高清 HDMI/USB编码器是一款1路HDMI或1路USB高清编码器&#xff0c;。可将 HDMI 或USB视频源编码压缩成网络流&#xff0c;通过有线网络…

springboot 3.x 之 集成rabbitmq实现动态发送消息给不同的队列

背景 实际项目中遇到针对不同类型的消息&#xff0c;发送消息到不同的队列&#xff0c;而且队列可能还不存在&#xff0c;需要动态创建&#xff0c;于是写了如下代码&#xff0c;实践发现没啥问题&#xff0c;这里分享下。 环境 springboot 3.2 JDK 17 rabbitMQ模型介绍 图片…

银河麒麟系统升级openssh至9.7p1

银河麒麟系统升级openssh至9.7p1 升级过程建议参照链接 https://blog.csdn.net/zt19820204/article/details/137877652 当前环境 开始安装 # 1.查看当前服务器的openssh版本 ssh -V# 2.openssh下载地址 https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/# 3.升级opens…

想停,不可能!

转融通出借数量突然暴增&#xff0c;逼得证监会火速出来辟谣&#xff0c;这是坊间这几天传得&#xff08;最&#xff09;火的事。 事情呢&#xff0c;一句话概括就是光6月12号那一天&#xff0c;就新增了1.7亿股&#xff0c;吓得大家都说是转融通疯狂报复来了&#xff01;但官家…

Google 新 AI 为视频生成配乐和对白;Runway 发布 Gen-3 视频生成模型丨 RTE 开发者日报 Vol.226

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE&#xff08;Real-Time Engagement&#xff09; 领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「…

烟雾自动监测识别摄像机

烟雾自动监测识别摄像机是现代城市安全管理的关键装备&#xff0c;其在各类场所的应用日益广泛&#xff0c;尤其在大型建筑、工厂和公共设施中&#xff0c;其重要性更为突出。该类摄像机采用先进的传感技术&#xff0c;能够实时监测环境中的烟雾密度和变化。通过高灵敏度的传感…

批量创建文件夹 就是这么简单 一招创建1000+文件夹

批量创建文件夹 就是这么简单 一招创建1000文件夹 在工作中&#xff0c;或者生活中&#xff0c;我们经常要用到批量创建文件夹&#xff0c;并且根据不同的工作需求&#xff0c;要求是不一样的&#xff0c;比如有些人需要创建上千个不一样名称的文件夹&#xff0c;如果靠手动创…

开发淘宝在线扭蛋机小程序:关键点与实战技巧

引言 在上一篇文章中&#xff0c;我们介绍了开发淘宝在线扭蛋机小程序的基本步骤和前期准备。但在实际开发过程中&#xff0c;还有一些关键点和实战技巧需要特别注意。本文将为您详细阐述这些关键点和技巧。 一、关键点 用户体验&#xff1a; 简洁明了的界面设计&#xff0c…

AI 视频生成工具 Sora 横空出世!一文带你了解 Sora:简介|主要功能|使用场景|平替工具等!

要说最近的头条热搜&#xff0c;非 Sora 莫属&#xff01;Sora 的诞生&#xff0c;再一次引发了人们对 AI 人工智能以及 AIGC 的关注。 对第一次听说 Sora 的人&#xff0c;可能会好奇&#xff0c;大家都在说的 Sora 是什么&#xff1f; Sora 是什么软件&#xff1f; Sora&a…