当前位置:

首页 > 编程开发 > Java线程安全与同步实例分析

Java线程安全与同步实例分析

线程安全问题多个线程可能会共享(访问)同一个资源比如访问同一个对象,同一个变量,同一个文件当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题,称为线程安全问题什么情况下会出现线程安全问题多个线程共享同一个资源且至少有一个线程正在执行写的操作实例:存钱取钱问题分别有存钱和取钱2个线程存钱取钱线程1余额线程21000《----1000------》10001000+1000-----》2000500《-----1000-500正确:结束后余额应该是1500,而不是500买票问题有卖票2个线程卖票卖票

本文目录

    线程安全问题

    多个线程可能会共享(访问)同一个资源

    比如访问同一个对象,同一个变量,同一个文件

    当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题,称为线程安全问题

    什么情况下会出现线程安全问题

    多个线程共享同一个资源

    且至少有一个线程正在执行写的操作

    实例:

    存钱取钱问题

    分别有存钱和取钱2个线程

       存钱                      取钱
       线程1         余额         线程2
       1000  《----1000------》 1000
       1000+1000-----》2000
                    500 《-----1000-500

    正确:结束后余额应该是1500,而不是500

    买票问题

    有卖票2个线程

       卖票                      卖票
       线程1         票数         线程2
       1000  《----1000------》 1000
       1000-1-----》999
                    999 《-----1000-1

    正确:结束后余额应该是998,而不是999

    买票问题错误(未线程同步)实例:

    public class love implements Runnable{
        private int piao=3000;//有3000张票
        public boolean sale() {//ture代表还有票;false代表没有票了
            if(piao<1) return false;
             piao--;//卖1张票
             
             //细化piao--;
             //寄存器=piao;
             //寄存器=寄存器-1;
             //piao=寄存器;
             
             String sk =Thread.currentThread().getName();//获取当前线程(买票窗口)的名字
             System.out.println(sk+"卖了1张票,还剩下"+piao+"张");
             return piao>1;
        }
        public void run() {
             while(sale());//循环执行;直至卖完票返回false
        }
    }
     
    public class Main {
        public static void main(String[] a) {
            love tjlove =new love();
            for(int i=1;i<=4;i++) {//循环4次;产生4个线程(窗口)卖票
                Thread tj = new Thread(tjlove());
                tj.setName(""+i);
                tj.start();
            }
        }
    }

    部分输出结果:

    Java线程安全与同步实例分析

    线程安全问题

    分析问题

    线程A和B对类中1个变量值为17进行+1操作
    最终结果为2个18

    解决方案

    加锁:

    过程:首先线程A先访问到这个17,读上来后进行加锁并进去+1的操作改为18
    并且17在加锁期间其它线程都不能访问
    改完之后再进行写入,然后再解锁17
    然后再由线程B去访问它,再进行加锁,重复上面操作变成19再解锁
    这样做能保证在同一时间只有1个线程去访问它,这样就保证了安全;之前错误是由于这些线程一起去访问了它

    线程同步

    刚刚所说的加锁操作便是线程同步技术

    可以使用线程同步技术来解决线程安全问题

    线程同步在Java里有2种做法:

    1.同步语句

    2.同步方法

    同步语句

    public class love implements Runnable{
    	private int piao=3000;//本人cpu单核性能过强,数据量大些才能看到是4个线程在卖票
    	public boolean sale() {
    		synchronized(this) {//1个线程获取这个对象的锁,并加锁;    synchronized作用于整个语句
    		//this指向当前对象
    		//不能用new Object();这样会产生新的对象,产生新的锁
    		//把this换成"123",效果基本一样;因为其存在常量值里,每次访问的对象一样
    			if(piao<1) return false;
    			piao--;
    			String sk =Thread.currentThread().getName();
    			System.out.println(sk+"卖了1张票,还剩下"+piao+"张");
    			return piao>0;
    			}
    	}
    	public void run() {
    		 while(sale());
    	}
    }

    部分输出结果:

    Java线程安全与同步实例分析

    synchronize(obj)的原理

    1.每个对象都有一个与它相关的内部锁(intrinsic lock)或者叫监视器锁(monitor lock)

    2.第一个执行到同步语句的线程可以获得 obj 的内部锁,在执行完同步语句中的代码后释放此锁

    3.只要一个线程持有了内部锁,那么其它线程在同一时刻将无法再获得此锁

    ✓ 当它们试图获取此锁时,将会进入BLOCKED状态

    4.多个线程访问同一个 synchronized(obj)语句时

    obj必须是同一个对象,才能起到同步的作用

    同步方法

    public class love implements Runnable{
        private int piao=3000;
        public synchronized boolean sale() { //synchronized作用于整个方法
                if(piao<1) return false;
                piao--;
                String sk =Thread.currentThread().getName();
                System.out.println(sk+"卖了1张票,还剩下"+piao+"张");
                return piao>0;
        }
        public void run() {
             while(sale());
        }
    }

    synchronized不能修饰构造方法

    同步方法的本质

    实例方法:synchronized (this)

    静态方法:synchronized (Class对象)

    同步语句比同步方法更灵活一点

    同步语句可以精确控制需要加锁的代码范围,减少处于BLOCKED状态的线程,充分利用劳动力

    使用了线程同步技术后

    虽然解决了线程安全问题,但是降低了程序的执行效率

    因为加了锁就会有处于等待的线程,多了加锁解锁的操作

    所以在真正有必要的时候,才使用线程同步技术

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 Java
    相关文章 更多
    Java单元测试入门:使用JUnit 5编写第一个测试用例
    Java单元测试入门:使用JUnit 5编写第一个测试用例

    面向初学者的JUnit 5实用入门指南。从测试概念、Maven依赖配置,到手把手编写首个单元测试用例及断言验证,助你掌握Java单元测试的核心流程。

    Java变量未初始化报错解析:局部变量与成员变量默认值差异
    Java变量未初始化报错解析:局部变量与成员变量默认值差异

    深入解析Java中局部变量未初始化编译报错与成员变量自动赋予默认值的机制差异,涵盖JVM内存分配、编译期确定性赋值检查与实际排查修复方案。

    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat
    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat

    详细讲解在Java中获取当前系统时间并进行格式化输出的两种核心方案:基于Java 8全新日期时间API的DateTimeFormatter与传统遗留的SimpleDateFormat,包含完整代码示例、线程安全机制对比及生产选型建议。

    Java中final与static final常量的定义及初始化规则
    Java中final与static final常量的定义及初始化规则

    深入解析Java中final变量与static final常量的定义、内存语义、初始化时机及合法赋值路径,涵盖编译期常量优化与实战避坑指南。

    Java抽象方法与接口方法的区别及选型建议
    Java抽象方法与接口方法的区别及选型建议

    深入对比Java中抽象类抽象方法与接口方法的语法演进、设计意图及运行期差异,并提供清晰的架构选型决策流程与实战范例。

    Java实现HTTP请求与JSON解析的完整代码示例
    Java实现HTTP请求与JSON解析的完整代码示例

    本文提供Java标准库HttpClient发起HTTP GET/POST请求并结合Jackson进行JSON数据反序列化与序列化的完整代码示例与工程实践指南。

    Java递归出现StackOverflowError的原因分析及栈空间优化方案
    Java递归出现StackOverflowError的原因分析及栈空间优化方案

    详细分析Java递归调用出现StackOverflowError的原因,结合代码说明线程栈、栈帧和递归深度之间的关系,并介绍终止条件排查、迭代改写、减少栈帧开销以及通过-Xss调整JVM栈空间的方法。

    Java空指针异常(NPE)的代码排查与修复实例
    Java空指针异常(NPE)的代码排查与修复实例

    针对Java中常见的NullPointerException(NPE),本文从堆栈日志定位、典型代码触发场景、具体修复代码对比到防御体系进行系统讲解,提供实用且易上手的排查与修复方案。

    selenium上传文件教程本地文件路径设置方法
    selenium上传文件教程本地文件路径设置方法

    深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

    针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。