Java多线程学习(四)

线程安全问题讨论

1.多线程并发操作同一数据时,就可能出现线程安全问题

2.使用同步技术解决,把操作数据的代码进行同步,不要多线程一起操作

案例:铁路售票,一共100张票,四个窗口进行售票

问题案例:

package javastudy01;

public class saleticket extends Thread{
	//问题1
     //private int ticket = 100 ;这是一个成员对象,下面的每一个对象都会产生自己的100张
	//此时所有的对象会共享一个ticket
	private  static int ticket = 100 ;  
	
	public void run(){
		while(true){
		if(ticket==0){
			break;
		}
		//问题2 :在此处模拟很多方法的同时进行
		try {
			Thread.sleep(10);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("这是第"+ticket-- +"张票");
	}
		
}
	
	
	

	public static void main(String[] args) {
			//四个线程,相当于四个售票的窗口
		   new saleticket().start();
		   new saleticket().start();
		   new saleticket().start();
		   new saleticket().start();
		   
		 
		 

	}

}

运行时出现问题

出现了卖负数的票;原因:

在方法中加上了睡眠,模拟了多线程同时执行,

当ticket =1时,一号窗口(线程1)在执行到sleep处会睡眠,此时ticket=1,线程2,3,4进入一样会睡眠,

但当1睡醒后,执行下面的代码ticket-- , ticket此时=0 ,然后线程2 醒了,执行ticket--,ticket=-1,跳过了条件

判断的==0 所以会无限执行下去,卖出负数张票。

2.所以解决以上问题需要用到同步技术

多线程并发想改变同一个数据时,建议使用同步代码块

package javastudy01;

import org.omg.CORBA.PRIVATE_MEMBER;

public class saleticket extends Thread{
	//问题1
     //private int ticket = 100 ;这是一个成员对象,下面的每一个对象都会产生自己的100张
	//此时所有的对象会共享一个ticket
	private  static int ticket = 100 ;  
	
	public void run(){
		while(true){
			//此处锁对象不能使用this,不能用private Object obj = new Object(),
			//可以使用	saleticket.class 它是唯一的
		 
			synchronized(saleticket.class){	
				if(ticket==0){
					break;
				}
				//问题2 :在此处模拟很多方法的同时进行
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				System.out.println("这是第"+ticket-- +"张票");
							}
				}
		
		}
	
	
	

	public static void main(String[] args) {
			//四个线程,相当于四个售票的窗口
		   new saleticket().start();
		   new saleticket().start();
		   new saleticket().start();
		   new saleticket().start();
		   
		 
		 

	}

}

 
	 	
	

运行结果

正常买票不出现负票情况;

再给出Runnable接口实现线程安全的代码;

package javastudy01;

public class runnablesale implements Runnable {

	public static void main(String[] args) {
		 runnablesale rs = new  runnablesale();
		 new Thread(rs).start();
		 new Thread(rs).start();
		 new Thread(rs).start();
		 new Thread(rs).start();
	
	}
	
	
	private int ticket = 100;   //此处不需要静态,因为在实现线程过程中rs作为一个对象传入,因而每一个线程的rs是同一个rs

	@Override
	public void run() {
		while(true){
			 //这里可以使用this是因为rs对象在实现时仅创建了一次,是唯一的
			synchronized(this){	
				if(ticket==0){
					break;
				}
				 
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				System.out.println("这是第"+ticket-- +"张票");
							}
				}
	}

}

运行结果

同上

猜你喜欢

转载自blog.csdn.net/watsonliuwho/article/details/82589879
今日推荐