Java线程安全与同步代码块
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java线程安全与同步代码块相关的知识,希望对你有一定的参考价值。
因为在电商网站工作的原因,对于秒杀、闪购等促销形式相当熟悉。无外乎商家拿出一定量的库存去做所谓的“亏本买卖”,其目的是用有限的库存去吸引无限的流量。然而,我却碰到过因为系统问题,导致秒杀品超卖的情况。可怜的商户其实只提供了10双9.9元的童鞋做秒杀,却在瞬间内卖出了1000双!
类似这样的问题,在非线程安全的程序设计中十分常见,我们下面运行一个秒杀的程序:
public class SalesThread implements Runnable { private int stock = 10; public void run() { if(stock>0){ try{ Integer processingTime = new Random().nextInt(1000); System.out.println(Thread.currentThread().getName() +":订单处理中..."); Thread.sleep(processingTime); System.out.println(Thread.currentThread().getName() + ":交易成功,库存余量:" + --stock ); }catch(InterruptedException e){ e.printStackTrace(); } } } }
public static void main(String[] args) { SalesThread thread = new SalesThread(); for(int i=0;i<30;i++) { new Thread(thread,"client-"+i+1).start(); } }
我们试图使用线程类内部的stock>0来限制10个库存的销售量,但实际运行结果却是如下...每个人都买到了我的秒杀品!赔死了!心塞塞!
client-01:订单处理中... client-11:订单处理中... client-31:订单处理中... client-21:订单处理中... client-51:订单处理中... client-41:订单处理中... client-61:订单处理中... client-71:订单处理中... client-91:订单处理中... client-81:订单处理中... client-101:订单处理中... client-111:订单处理中... client-131:订单处理中... client-121:订单处理中... client-141:订单处理中... client-151:订单处理中... client-161:订单处理中... client-171:订单处理中... client-191:订单处理中... client-181:订单处理中... client-201:订单处理中... client-111:交易成功,库存余量:8 client-71:交易成功,库存余量:9 client-291:订单处理中... client-261:订单处理中... client-281:订单处理中... client-271:订单处理中... client-251:订单处理中... client-241:订单处理中... client-231:订单处理中... client-221:订单处理中... client-211:订单处理中... client-41:交易成功,库存余量:7 client-101:交易成功,库存余量:6 client-51:交易成功,库存余量:5 client-251:交易成功,库存余量:4 client-291:交易成功,库存余量:3 client-171:交易成功,库存余量:2 client-271:交易成功,库存余量:1 client-01:交易成功,库存余量:0 client-121:交易成功,库存余量:-1 client-201:交易成功,库存余量:-2 client-261:交易成功,库存余量:-3 client-281:交易成功,库存余量:-4 client-151:交易成功,库存余量:-5 client-131:交易成功,库存余量:-6 client-221:交易成功,库存余量:-7 client-241:交易成功,库存余量:-8 client-61:交易成功,库存余量:-9 client-21:交易成功,库存余量:-10 client-161:交易成功,库存余量:-11 client-81:交易成功,库存余量:-12 client-191:交易成功,库存余量:-13 client-141:交易成功,库存余量:-14 client-211:交易成功,库存余量:-15 client-11:交易成功,库存余量:-16 client-31:交易成功,库存余量:-17 client-231:交易成功,库存余量:-18 client-181:交易成功,库存余量:-19 client-91:交易成功,库存余量:-20
java提供给我们一个synchronized关键字,我们理解为同步锁,当操作多个线程共享的数据时,将必须保护的操作放置到synchronized关键字的作用域——同步代码块中,即可保证,在同一时间,只有一个线程,对共享数据进行操作,将SalesThread源代码修改为如下形式:
public class SalesThread implements Runnable { private int stock = 10; private Object lock = new Object(); public void run() { while(stock>0){ synchronized(lock){ if(stock>0){ try{ Integer processingTime = new Random().nextInt(1000); System.out.println(Thread.currentThread().getName() +":订单处理中..."); Thread.sleep(processingTime); System.out.println(Thread.currentThread().getName() + ":交易成功,库存余量:" + --stock ); }catch(InterruptedException e){ e.printStackTrace(); } } } } } }
处理结果如下:
client-1:订单处理中... client-1:交易成功,库存余量:9 client-8:订单处理中... client-8:交易成功,库存余量:8 client-30:订单处理中... client-30:交易成功,库存余量:7 client-30:订单处理中... client-30:交易成功,库存余量:6 client-29:订单处理中... client-29:交易成功,库存余量:5 client-28:订单处理中... client-28:交易成功,库存余量:4 client-27:订单处理中... client-27:交易成功,库存余量:3 client-25:订单处理中... client-25:交易成功,库存余量:2 client-26:订单处理中... client-26:交易成功,库存余量:1 client-24:订单处理中... client-24:交易成功,库存余量:0
以上是关于Java线程安全与同步代码块的主要内容,如果未能解决你的问题,请参考以下文章
JAVA之旅(十三)——线程的安全性,synchronized关键字,多线程同步代码块,同步函数,同步函数的锁是this