多线程编程(二)——并发问题

一、首先看下面一个例子

      已知车票售卖系统中有1000张车票,有3个售票点在随机售卖,请模拟出这3个售票点卖出这些车票的过程。

根据以上题目,编程如下:

/**
 * 模拟3个售票点,共同卖出1000张票
 *
 */
public class Test1 {
	public static void main(String[] args) {
		
		SellTicket st = new SellTicket();
		Thread t1 = new Thread(st);
		Thread t2 = new Thread(st);
		Thread t3 = new Thread(st);
		
		t1.start();
		t2.start();
		t3.start();
	}
}
class SellTicket implements Runnable
{
	int total=1000;
	int sold=0;

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true){
            if(total>0){
            	try {
    				Thread.sleep(1000);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    			sold++;
    			System.out.println(Thread.currentThread().getName()+
    					"正在售出第"+sold+"张车票");
    			total--;
            }else  if(total<0){
            	break;
            }
		}
	}
}
输出结果

Thread-1正在售出第2张车票
Thread-2正在售出第3张车票
Thread-0正在售出第1张车票
Thread-0正在售出第5张车票
Thread-2正在售出第5张车票
Thread-1正在售出第6张车票
Thread-2正在售出第7张车票
Thread-0正在售出第8张车票
Thread-1正在售出第9张车票

从结果中可以看出

1、没有卖出第4张车票。        2、第5张车票被卖出了2次。

这明显有悖于常理“1张车票,怎么能被两个人同时买到呢?”

分析原因:

    从以上代码中可以看到,st对象被3个线程同时启动,因此st对象中是变量是对于这3个线程而言是共享的,任何一个线程都可以调用。

     在执行 total- -之前,存在sleep(1000)。

      线程-0在售出第4张车票的时候,即执行到sold++完毕后,此时在st对象中 sold=4;同时线程-2 刚好等待了1s,也马上执行到sold++,执行完成sold++后,st对象中sold=5;由于3个线程共享st对象中的变量,当线程-0开始执行System.out.println( )时,它调取st对象中的sold变量=5,因此线程-0输出5;线程-2同样马上执行System.out.println()

,它也调取st对象中的sold变量=5,线程-2输出5。在这期间,线程-1还在等待。

       这就是多线程并发,带来的线程安全问题。

二、怎样处理线程并发造成的影响?

       办法很简单,即想办法保证“一个线程在执行某段代码的时候,其他线程需要等待它执行完成后才能继续执行”,即保证代码的"原子性"。

        具体怎样操作呢?在需要保证“原子性”的代码外加上synchronized(Object){ …}。

        为以上代码增加Synchronized后,如下:

/**
 * 模拟3个售票点,共同卖出1000张票
 *
 */
public class Test1 {
	public static void main(String[] args) {
		
		SellTicket st = new SellTicket();
		Thread t1 = new Thread(st);
		Thread t2 = new Thread(st);
		Thread t3 = new Thread(st);
		
		t1.start();
		t2.start();
		t3.start();
	}
}
class SellTicket implements Runnable
{
	int total=1000;
	
	public void run() {
		// TODO Auto-generated method stub
			while(true){
				synchronized(this){
	            if(total>0){
	    			
	    			System.out.println(Thread.currentThread().getName()+
	    					"正在售出第"+total+"张车票");
	    			try {
	    				Thread.sleep(1000);
	    			} catch (InterruptedException e) {
	    				// TODO Auto-generated catch block
	    				e.printStackTrace();
	    			}
	    			total--;
	    			
	            }else  if(total<0){
	            	break;
	            }
			}
		}
	}
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值