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基础之多线程

JAVA之旅(十三)——线程的安全性,synchronized关键字,多线程同步代码块,同步函数,同步函数的锁是this

Java线程安全问题代码实现

Java线程同步块行为 - 同步与同步()? [复制]

Java多线程:线程同步详解

JAVA多线程_线程安全问题