synchronized 修饰的方法无法实现互斥的问题解决
来源:互联网 发布:mac pro 2016电池容量 编辑:程序博客网 时间:2024/06/07 20:30
模拟订票场景,总共10张票,但是有20个人想要购买,所以定义了一个订票管理类专门负责操作这10张票,当然,操作票的时候使用到了synchronized,另外定义了一个调用订票方法的线程类用于模拟想要买票的人,然后创建20个线程模拟20个人来订票。但是运行测试的结果却并没有成功模拟这10张票的售卖过程,原因和处理分析如下:
订票管理类
设置 10 张票出售。
package com.example.study;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * 订票管理 * * @author 李关钦 * @date 2017年6月7日 */public class TicketManager { public static int ticket = 10;// 默认总共 10 张票 private static final Logger logger = LoggerFactory.getLogger(TicketManager.class); /** * 售票,先检查是否有票,有则对原票数减一 * * @return */ public synchronized boolean buyTicket() { // 延迟 1 秒钟,模拟实际情况中的处理时间 try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } if (ticket > 0) { logger.info("current thread name is [{}] , before is [{}] , after is [{}]", Thread.currentThread().getName(), ticket, --ticket); return true; } else { logger.info("current thread name is [{}] , ticket is [{}] , The ticket has been sold out !!!", Thread.currentThread().getName(), ticket); return false; } }}
订票线程
模拟订票的人。
package com.example.study;/** * 订票线程,实现 Runnable 接口 * * @author 李关钦 * @date 2017年6月7日 */public class BuyTicketRunnable implements Runnable { private TicketManager ticketManager = new TicketManager(); @Override public void run() { ticketManager.buyTicket(); }}
测试
创建 20 个线程,模拟
package com.example.study;/** * * * @author 李关钦 * @date 2017年6月7日 */public class Test { public static void main(String[] args) { // 设置 20 个进程,模拟 20 个人订票 for (int i = 0; i < 20; i++) { Thread thread = new Thread(new BuyTicketRunnable()); thread.start(); } }}
结果:
从运行结果可以看到,线程 10 和线程 8 订票的结果一样了,也就说明了使用 synchronized 修饰的订票方法不起效,达不到互斥的效果。
原因:
在以上代码中,每创建一个订票线程 BuyTicketRunnabl创建一个 TicketManager 订票管理对象与之对应,也就是说创建了 20 个订票线程就会有 20 个对应的订票管理对象去操作票数,所以达不到互斥的关系。
解决方法:
在订票线程中用 static 修饰订票管理对象,使订票管理对象成为全局变量,与其他线程共享,所以 创建的 20 个线程就会共享同一个 TicketManager 订票管理对象,而 TicketManager 里面的订票方法又是使用 synchronized 的,所以就会达到互斥的效果。
package com.example.study;/** * 订票线程,实现 Runnable 接口 * * @author 李关钦 * @date 2017年6月7日 */public class BuyTicketRunnable implements Runnable { private static TicketManager ticketManager = new TicketManager(); @Override public void run() { ticketManager.buyTicket(); }}
阅读全文
0 0
- synchronized 修饰的方法无法实现互斥的问题解决
- 关于java synchronized修饰方法时实现线程互斥遇到的问题
- 线程方法synchronized修饰符的作用
- 使用Lock实现互斥(synchronized的一个替代)
- 使用Lock实现互斥(synchronized的一个替代)
- synchronized修饰方法,保证数据同步准确性,限制线程互斥访问
- 线程的同步互斥synchronized
- synchronized修饰static方法与非static方法的区别
- synchronized修饰静态方法和非静态方法的总结
- bash实现互斥、信号量的方法
- 操作系统互斥的实现方法
- synchronized修饰的同步方法的个人理解
- java中synchronized修饰的方法和代码块
- java中synchronized修饰的方法或代码块和static synchronized修饰方法或代码块的区别
- synchronized修饰非static方法与修饰static方法的区别
- synchronized 锁的实现方法
- synchronized(object)的应用场景以及与synchronized修饰方法的区别
- java的多线程同步互斥:synchronized的乱用
- jieba分词
- 关于String s = new String("abc")的知识
- 什么是时钟周期?什么是机器周期?什么是指令周期?
- Hibernate5.2.5的配置
- hibernate中session中的update方法,改动了一下,让数据库中原有的属性不变,只更新传入对象中改动的属性
- synchronized 修饰的方法无法实现互斥的问题解决
- UE4引擎学习笔记:Blueprints Visual Scripting->Basic Scripting
- Android OPenGL 初体验
- 手把手带你撸一套Android简易ORM框架
- web服务器接口返回参数有null值
- ES6中的export、import、export default详解
- 从二分类到多分类的迁移策略
- js中使用background-size等带“-”的css样式
- JavaScript基础部分(三)