博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Synchronized锁不住Integer
阅读量:2291 次
发布时间:2019-05-09

本文共 2323 字,大约阅读时间需要 7 分钟。

本来想写一个程序,模拟12306抢票,但是最后发现Synchronized锁不住Integer,记录一下。

public class TicketConsumer implements Runnable{	private Integer i;	public TicketConsumer(int i) {		super();		this.i = i;	}	@Override	public void run() {		while(true) {			synchronized (i) {				if(i>0) {					try {						Thread.sleep(100);	// 模拟抢票延迟					} catch (InterruptedException e) {						e.printStackTrace();					}					System.out.println(Thread.currentThread().getName()+"抢到了第"+i--+"张票");				}else {					return;				}			}		}	}}

public class Test1 {	public static void main(String[] args) {		TicketConsumer ticket = new TicketConsumer(new Integer(10));		Thread t1 = new Thread(ticket,"张三");		Thread t2 = new Thread(ticket,"李四");		t1.start();		t2.start();	}}

大眼一瞟,似乎没问题,但是运行就出了问题,两人抢到了同一张票

运行结果
张三抢到了第10张票
李四抢到了第9张票
张三抢到了第9张票
李四抢到了第8张票
李四抢到了第7张票
张三抢到了第6张票
李四抢到了第5张票
张三抢到了第4张票
李四抢到了第4张票
张三抢到了第3张票
张三抢到了第2张票
李四抢到了第1张票

原因就是,Integer取值如果是在[-128,127]之间,系统会从常量池中取值,如果超出这个范围,系统会自动new一个新对象,所以每次对象都不一样

Integer i = 1;System.out.println(System.identityHashCode(i));System.out.println(System.identityHashCode(++i));StringBuilder sb = new StringBuilder("张三");System.out.println(System.identityHashCode(sb));sb.append("李四");System.out.println(System.identityHashCode(sb));
运行结果
366712642
1829164700
2018699554
2018699554

Integer在自增后,内存地址就变了,而StringBuilder却不会变,一旦变化Synchronized每次锁的就不是同一个对象,所以锁不住。

解决办法:

可以把Integer单独放到一个类中,Synchronized这个类的对象,就可以了

public class Ticket {	int count;	public Ticket(int count) {		super();		this.count = count;	}	}
public class TicketConsumer implements Runnable{	private Ticket ticket;	public TicketConsumer(Ticket ticket) {		super();		this.ticket = ticket;	}	@Override	public void run() {		while(true) {			try {				Thread.sleep(100);	// 模拟抢票延迟			} catch (InterruptedException e) {				// TODO Auto-generated catch block				e.printStackTrace();			}			synchronized (ticket) {				if(ticket.count>0) {					System.out.println(Thread.currentThread().getName()+"抢到了第"+ticket.count--+"张票");				}else {					return;				}			}		}	}}
public class Test1 {	public static void main(String[] args) {		TicketConsumer ticket = new TicketConsumer(new Ticket(10));		Thread t1 = new Thread(ticket,"张三");		Thread t2 = new Thread(ticket,"李四");		t1.start();		t2.start();	}}

 

运行结果
李四抢到了第10张票
张三抢到了第9张票
张三抢到了第8张票
李四抢到了第7张票
张三抢到了第6张票
李四抢到了第5张票
李四抢到了第4张票
张三抢到了第3张票
张三抢到了第2张票
李四抢到了第1张票

O了…

转载地址:http://mcsnb.baihongyu.com/

你可能感兴趣的文章
Foreign Language_english_语法分析_1
查看>>
Machine Learning_mahout_20news_caution
查看>>
R_bioinfomatics_heatmap
查看>>
8086_proteus_masm配置
查看>>
8086_proteus_all_dsn
查看>>
Others_各行业优秀的人
查看>>
欢迎使用CSDN-markdown编辑器
查看>>
DeepLearning 知识点整理
查看>>
stdcall 标准winNTdll 编写 与 调用
查看>>
Android 搭建
查看>>
Java 配置
查看>>
多个Activity的完全退出
查看>>
自定义android控件
查看>>
tomcat c/s 三层架构
查看>>
代码_多进程_简单实例
查看>>
转载_消息机制
查看>>
代码_网络_FTP
查看>>
代码_网络_WWW
查看>>
UIView常用属性和函数
查看>>
UIButton常用属性和函数详解
查看>>