线 程 同 步、线程的死锁问题

news2024/11/24 17:24:31
线程同步:
模拟售票程序出现问题:
            当多个线程同时访问共享数据时,产生无序、重复、超额售票等多线程安全问题
解决:将多个线程需要访问的共享数据,包装起来视为一个整体,确保一次只有一个线程执行流访问共享数据
Java为上述问题提供了相应的解决办法:
    1、同步代码块
         synchronized(同步监视器){
            //多个线程需要访问的共享数据
         }
         同步监视器:俗称“锁” ,可以使用任意类型的对象充当。但是必须保证多个线程持有 同一把锁(同一个对象)

    2、同步方法
    3、同步锁 Lock

package Thread;

public class TicketWindow2 implements Runnable{
    int tick=100;
    Object obj=new Object();
    @Override
    public void run() {
        while (true){
            synchronized (obj){
                if (tick>0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                    }
                    System.out.println(Thread.currentThread().getName()+"完成售票,剩余票数:"+ --tick);
                }
            }
        }
    }
}
package Thread;

public class TicketWindowTest2 {
    public static void main(String[] args) {
        TicketWindow2 tw2=new TicketWindow2();
        Thread t1=new Thread(tw2,"一号窗口");
        t1.start();
        Thread t2=new Thread(tw2,"二号窗口");
        t2.start();
        Thread t3=new Thread(tw2,"三号窗口");
        t3.start();

    }
}

 同步方法 :

在方法声明处加 synchronized 关键字
                如:
                    public synchronized void show() {
                 }
package Thread;

public class TicketWindow2 implements Runnable{
    int tick=100;
    Object obj=new Object();
    @Override
    public void run() {
        while (true){
           /* synchronized (obj){
                if (tick>0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                    }
                    System.out.println(Thread.currentThread().getName()+"完成售票,剩余票数:"+ --tick);
                }
            }*/
            show();
        }
    }
    public synchronized void show(){
        if (tick>0){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            }
            System.out.println(Thread.currentThread().getName()+"完成售票,剩余票数:"+ --tick);
        }
    }
}

同步锁:

Lock为接口,创建实例

unlock一定要执行,所以放到try-catch-finally中

package Thread;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TicketWindow2 implements Runnable{
    int tick=100;
    Object obj=new Object();
    Lock l=new ReentrantLock();
    @Override
    public void run() {
        while (true){
           /* synchronized (obj){
                if (tick>0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                    }
                    System.out.println(Thread.currentThread().getName()+"完成售票,剩余票数:"+ --tick);
                }
            }*/


//            show();

            l.lock();//上锁
            try {
                if (tick>0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                    }
                    System.out.println(Thread.currentThread().getName()+"完成售票,剩余票数:"+ --tick);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                l.unlock();//释放锁
            }

        }
    }
    public synchronized void show(){
        if (tick>0){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            }
            System.out.println(Thread.currentThread().getName()+"完成售票,剩余票数:"+ --tick);
        }
    }
}

 

当前的锁为悲观锁 

 

线程同步:
模拟售票程序出现问题:
            当多个线程同时访问共享数据时,产生无序、重复、超额售票等多线程安全问题
解决:将多个线程需要访问的共享数据,包装起来视为一个整体,确保一次只有一个线程执行流访问共享数据
Java为上述问题提供了相应的解决办法:
    1、同步代码块
         synchronized(同步监视器){
            //多个线程需要访问的共享数据
         }
         同步监视器:俗称“锁” ,可以使用任意类型的对象充当。但是必须保证多个线程持有 同一把锁(同一个对象)

    2、同步方法:在方法声明处加 synchronized 关键字
                    如:
                        public synchronized void show() {
                     }
                注意:非静态同步方法隐式的锁为 this(即当前对象)
                      静态同步方法的锁为对应类的Class实例
    3、同步锁 Lock

Exer:

银行有一个账户。
有两个储户分别向同一个账户存3000元,每次存1000,存3次。每次存完打印账户余额.
问题:该程序是否有安全问题,如果有,如何解决?
【提示】
1,明确哪些代码是多线程运行代码,须写入run()方法
2,明确什么是共享数据。
3,明确多线程运行代码中哪些语句是操作共享数据的。
package Exer;
/*
银行有一个账户。
有两个储户分别向同一个账户存3000元,每次存1000,存3次。每次存完打印账户余额.
问题:该程序是否有安全问题,如果有,如何解决?
【提示】
1,明确哪些代码是多线程运行代码,须写入run()方法
2,明确什么是共享数据。|
3,明确多线程运行代码中哪些语句是操作共享数据的。

 */
public class Exer {
    public static void main(String[] args) {
        Account account=new Account();
        Customer ca=new Customer(account);
        Customer cb=new Customer(account);
        new Thread(ca,"用户A").start();
        new Thread(cb,"用户B").start();

    }
}
package Exer;

public class Account {
    private double balance;

    public Account() {
    }

    public Account(double balance) {
        this.balance = balance;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }
    //存款
    public synchronized void deposit(double amount){
        balance+=amount;
        System.out.println(Thread.currentThread().getName()+"成功存入:"+amount+"余额为:"+balance);
    }
}
package Exer;

public class Customer implements Runnable {
    private Account account;

    public Customer() {
    }

    public Customer(Account account) {
        this.account = account;
    }

    public Account getAccount() {
        return account;
    }

    public void setAccount(Account account) {
        this.account = account;
    }

    @Override
    public void run() {
        for (int i = 0; i <3; i++) {
            account.deposit(1000);
        }
    }
}

 

 补充:互斥锁

 

 

线程的死锁问题: 

 

 

package Thread;

public class DeadLockTest {
    public static void main(String[] args) {
        DeadLock dl=new DeadLock();
        new Thread(dl).start();
        new Thread(dl).start();
    }
}
class DeadLock implements  Runnable{
    boolean flag=true;
    static Object obj1=new Object();//共享数据1
    static Object obj2=new Object();//共享数据2
    @Override
    public void run() {
        if (flag){
            synchronized (obj1){
                System.out.println("获取共享数据1,等待共享数据2....");

                synchronized (obj2){
                    System.out.println("-----------------------");
                }
            }
        }else {
            synchronized (obj2){
                System.out.println("获取共享数据2,等待共享数据1....");

                synchronized (obj1){
                    System.out.println("*************************");
                }

            }
        }
    }
}

------------------------------------------------------------------------------------------------------------ 

 

 

 将问题放大:

 

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

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

相关文章

春节福利丨神策数据 2022 年数字化营销资料打包全送

2022 年&#xff0c;神策数据出品多份行业研究报告&#xff0c;覆盖银行、证券、零售、教育、电商、融合媒体等多个行业&#xff0c;帮助更多企业通过多视角洞见紧握数字化营销的方向和趋势&#xff0c;用方法论结合落地实践驱动企业数字化经营。01B2B 电商数字化运营聚焦四类 …

【自学Python】Python查找字符串位置

Python查找字符串位置 大纲 Python查找字符串位置教程 在开发过程中&#xff0c;很多时候我们有在一个 字符串 中查找另一个字符串位置的需求&#xff0c;在 Python 中&#xff0c;在一个字符串中查找另一个字符串的位置我们使用 index() 函数。 index() 函数的功能与 find(…

力扣(78.90)补9.22

78.子集 感觉不太难&#xff0c;但是就是不会写。感觉回溯里有很多细节问题。 class Solution { private: vector<vector<int>> res; vector<int> num; void back(vector<int>& nums,int index,int end){ res.push_back(num); …

【JavaEE初阶】第三节.多线程基础篇

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 文章目录 前言 一、认识线程 二、多线程程序 2.1 第一个Java多线程程序 2.2 怎么样观察线程的详细情况 2.3 sleep方法 2.4 run 和 start 方法的区别是什么 三、创…

在springboot中配置热部署

今天什么节日也不是&#xff0c;那就祝大家今天快乐。 热部署 所谓热部署&#xff0c;就是在应用正在运行的时候升级软件&#xff0c;却不需要重新启动应用。对于Java应用程序来说&#xff0c;热部署就是在运行时更新Java类文件。在以往&#xff0c;我们对java代码进行修改之后…

【HBU】大一下期末重点

物理简答题一、牛顿第二定律&#xff08;Fdp/dt &#xff09;&#xff1a;1. 飞机怕小鸟:Fdp/dt 力与作用时间的乘积等于物体动量的变化。由于小鸟与飞机相对速度很大&#xff0c;作用时间很短,产生的作用力很大&#xff0c;当小鸟与飞机向撞&#xff0c;效果与同质量炮弹撞飞机…

正则表达式入门及常用正则表达式

常用正则表达式 1 正则表达式的基础概念 1.1 预定义字符 . 表示任何字符&#xff08;与行结束符可能匹配也可能不匹配&#xff09; \d 数字&#xff1a;[0-9] \D 非数字字符&#xff1a;[^0-9] \s 空白字符&#xff1a;[\t\n\xoB\f\r] \S 非空白字符&#xff1a;[^\s] \w 单…

k8s的YAML部署rocketmq记录

说明 测试环境是k8s集群&#xff0c;在上边部署一套单节点的rocketmq nameserver部署 Service和StatefulSet脚本如下 apiVersion: v1 kind: Service metadata:labels:app: rocketmqnamesrvname: rocketmqnamesrv spec:type: ClusterIPports:- port: 9876targetPort: 9876na…

Pytorch深度学习【十四】

批量归一化 归一化 损失出现在最后&#xff0c;后面的层(高级语义层)训练较快数据输入在最底部 底部的层训练慢底部层一变化&#xff0c;所有高级语义层都得跟着变最后的那些层需要重新学习多次—收敛速度变慢 问题—是否可以在学习底部层的时候避免变化顶部层 批量归一化 固定…

8 个精彩的免费 G​​IS 软件资源分享

有人说&#xff1a;一个人从1岁活到80岁很平凡&#xff0c;但如果从80岁倒着活&#xff0c;那么一半以上的人都可能不凡。 生活没有捷径&#xff0c;我们踩过的坑都成为了生活的经验&#xff0c;这些经验越早知道&#xff0c;你要走的弯路就会越少。 GIS 软件有两种通用格式&a…

【面试题】2023年前端最新面试题-性能优化篇

原文见&#xff1a;语雀&#xff08;https://www.yuque.com/deepstates/interview/xtt59x&#xff09; ● 性能指标 ● 分析工具 ● 优化方式 ○ 加载 ○ 渲染 ● 专题优化 ○ 技术栈&#xff1a;react ○ 浏览器 ○ 打包工具&#xff1a;webpack ● 项目 ⭐️⭐️⭐️ 相关知…

如何隐藏电脑硬盘分区?

无论是个人还是公司的电脑我们都会储存一些重要的数据&#xff0c;有些甚至还是涉及个人隐私或公司的商业机密。为了更好地保护电脑磁盘中的重要资料&#xff0c;部分用户希望能将硬盘分区隐藏起来。那么怎么隐藏硬盘分区呢&#xff1f;方法一&#xff1a;使用磁盘管理隐藏硬盘…

将vscode打造为你的开发工具的首选

文章目录前言vscode主要配置vscode的两个主要快捷键Java配置JDK和Gradle环境主要插件常见的配置launch.json配置运行测试用例常见问题Python主要插件settings.json配置Javascript/typescript常用插件settings.json样例Golang参考前言 什么是IDE? IDE 文本编辑 搜索 代码导…

Matlab矩阵和数组的操作

一、矩阵的建立 1、直接输入法 将矩阵的元素用方括号括起来&#xff0c;按矩阵行的顺序输入各元素&#xff0c;同一行的各元素之间用空格或逗号分隔&#xff0c;不同行的元素之间用分号分隔。 A [16 3 2 13; 5 10 11 8; … 9 6 7 12; 4 15 14 1] A 16 3 2 13 5 10 11 8 9 6…

如何有效的增加 shopee 的流量?

很多卖家选择在跨境电商平台开店。说到跨境电商&#xff0c;大家首先想到的应该是亚马逊、易趣等电商平台&#xff0c;边肖会在shopee平台上给大家带来店铺。新店如何获得流量&#xff1f;有哪些方式&#xff1f;米贸搜为你整理如下&#xff1a;shopee店铺如何获取流量&#xf…

Python学习笔记——函数

函数是组织好的&#xff0c;可重复使用的&#xff0c;用来实现单一&#xff0c;或相关联功能的代码段。能提高应用的模块性&#xff0c;和代码的重复利用率。定义函数定义函数使用关键字def&#xff0c;后接函数名&#xff0c;再后接放在圆括号&#xff08;&#xff09;中的可选…

P1036 [NOIP2002 普及组] 选数————C++

题目 [NOIP2002 普及组] 选数 题目描述 已知 nnn 个整数 x1,x2,⋯,xnx_1,x_2,\cdots,x_nx1​,x2​,⋯,xn​&#xff0c;以及 111 个整数 kkk&#xff08;k<nk<nk<n&#xff09;。从 nnn 个整数中任选 kkk 个整数相加&#xff0c;可分别得到一系列的和。例如当 n4n4…

支持ITIL的IT帮助台

什么是ITIL 信息技术基础架构库 &#xff08;ITIL&#xff09; 是一套集成的最佳实践&#xff0c;旨在帮助企业向客户提供 IT 服务。ITIL是由中央设计的广泛采用的框架 计算机和电信局&#xff08;CCTA&#xff09;&#xff0c;英国的政府机构;它目前由AXELOS Ltd拥有。 ITIL…

【微信小程序】实用教程03-自定义底部导航(含自定义tabBar导航高亮需点击两次的解决方案)

开始前&#xff0c;请先完成底部导航的开发&#xff0c;详见 【微信小程序】实用教程01-注册登录账号&#xff0c;获取 AppID、下载安装开发工具、创建项目、上传体验 显然&#xff0c;纯文字的底部导航有点low&#xff0c;还是需要有图标的才酷&#xff0c;下面我们一起来实…

python的numpy的用法总结

本文总结Numpy的用法&#xff0c;建议先学习python的container 基础。numpy可以理解列表或数组。一个numpy数组是一个由不同数值组成的网格。网格中的数据都是同一种数据类型&#xff0c;可以通过非负整型数的元组来访问。维度的数量被称为数组的阶&#xff0c;数组的大小是一个…