线程的同步
发布日期:2022-02-06 00:27:00
浏览次数:28
分类:技术文章
本文共 2338 字,大约阅读时间需要 7 分钟。
多线程共享数据引发的问题
用一个简单的例子来说,就是我们经常遇到的过年抢车票的问题,以前人们是去车站排队,先到先得,现在随着互联网的发展,我们可以在网上购票了,现在我们使用多线程来模拟抢票过程,每个人机会一样。
关键代码如下:/** * 线程不安全的网络抢票 * */public class Site implements Runnable{ private int count=10; //记录剩余票数 private int num = 0; //记录买到第几张票 public void run(){ while(true){ //没有余票时,跳出循环 if(count<=0){ break; } //第一步:修改数据 num++; count--; try { Thread.sleep(500); //模拟网络延时 } catch (InterruptedException e) { e.printStackTrace(); } //第二步:显示信息 System.out.println(Thread.currentThread().getName()+"抢到第"+num+"张票,剩余"+count+"张票!"); } }}//测试类public class Test { public static void main(String[] args) { Site site = new Site(); Thread person1= new Thread(site,"桃跑跑"); Thread person2= new Thread(site,"抢票代理"); Thread person3= new Thread(site,"黄牛党"); System.out.println("********开始抢票********"); person1.start(); person2.start(); person3.start(); }}看结果显示如下问题: 不是从第一张票开始 存在多人抢到一张票的情况 有些票号没有被抢到
这些都是由于多个线程并发操作统一共享资源,带来的数据不安全问题,要解决这样的问题,我们就需要使用到线程同步。
线程同步的实现
什么是线程同步 当两个或多个线程需要访问同一资源时,需要以某种顺序来确保该资源某一时刻只能被一个线程使用,这就是线程同步采用线程同步来控制线程的执行有两种方式,即同步带吗方法和同步代码块。这两种方法都是用synchronized关键字实现。
通过在方法申明中加入synchronized关键字实现同步方法,其语法如下:
访问修饰符 synchronized 返回类型 方法名(参数列表){//省略方法体…} 或者 synchronized 访问修饰符 返回类型 方法名(参数列表){//省略方法体…}在语法中:
synchronized是同步关键字 访问修饰符是指public,private等。使用同步方法解决上述代码,如下所示:
public class Site implements Runnable{ private int count=10; //记录剩余票数 private int num = 0; //记录买到第几张票 public void run(){ while(true){ if(count<=0){ break; } //第一步:修改数据 num++; count--; try { Thread.sleep(500); //模拟网络延时 } catch (InterruptedException e) { e.printStackTrace(); } //第二步:显示信息 System.out.println(Thread.currentThread().getName()+"抢到第"+num+"张票,剩余"+count+"张票!"); } }}
同步方法的缺陷
如果将一个运行时间较长的方法声明称synchronized将会影响效率同步代码块
语法:synchronized(syncObject){ //需要同步的代码 } 示例代码如下:public class Site implements Runnable { private int count = 10; // 记录剩余票数 private int num = 0; // 记录买到第几张票 public void run() { while (true) { //同步代码块 synchronized (this) { // 没有余票时,跳出循环 if (count <= 0) { break; } // 第一步:修改数据 num++; count--; try { Thread.sleep(500); // 模拟网络延时 } catch (InterruptedException e) { e.printStackTrace(); } // 第二步:显示信息 System.out.println(Thread.currentThread().getName() + "抢到第" + num + "张票,剩余" + count + "张票!"); } } }}
转载地址:https://blog.csdn.net/weixin_46175284/article/details/105546381 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
感谢大佬
[***.8.128.20]2024年04月23日 05时16分41秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
Linux服务器网络开发模型
2019-04-27
nginx虚拟目录设置 alias 和 root
2019-04-27
理解http响应头中的Date和Age
2019-04-27
四层和七层负载均衡的区别
2019-04-27
设置Squid Cache_mem大小
2019-04-27
squid日志文件太大,怎样处理?
2019-04-27
让Squid 显示本地时间
2019-04-27
linux mysql 命令 大全
2019-04-27
清除Squid缓存的小工具
2019-04-27
Varnish Cache 3.0.0安装
2019-04-27
深入探讨Varnish缓存命中率
2019-04-27
Linux下文件如果没有权限不能被Apache访问
2019-04-27
Linux内核学习四库全书
2019-04-27
Linux内核模块编程入门
2019-04-27
使用Cacti监控你的网络Cacti的安装
2019-04-27
2011年6月编程语言关注度排行
2019-04-27
Varnish使用小结
2019-04-27
千万级并发HAproxy均衡负载系统介绍
2019-04-27
什么是A记录、MX记录、CNAME记录
2019-04-27