线程安全与同步线程

线程不安全:

数据有负数,相同的情况
比如在进行抢票的时候。可能会出现在第数据不准确的现象

public class Unsafe implements Runnable {
	private static int ticketNum=10;
	private boolean flag=true;
	

	@Override
	public void run() {//run 不可以throws异常。
		while(flag) {
			test();
			if(ticketNum<0) {
				break;
			}
			
		}
		
	}
	public static void test() {
		try {
			Thread.sleep(100);//会出现数据异常的情况。
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"--->"+ticketNum--);
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//一个资源
		
		System.out.println(Thread.currentThread().getName());//该线程即是main方法。
		
		Unsafe web=new Unsafe();
		//多个代理(也即是意味着并发)
		new Thread(web,"1").start();
		new Thread(web,"2").start();
		new Thread(web,"3").start();
		new Thread(web,"4").start();
		
	}


}

线程同步:

在访问时加入锁机制。当一个线程获得对象的排他锁,独占资源,其他线程必须等待

  • 使用后释放锁即可,
  • 但是会存在很多的性能的问题。
  • 1.队列,2.锁机制
  • synchronize包括两种用法:synchronize方法和synchronize块
    public synchronized void test()
    synchronize块:synchronized(object){}

修改之后的代码


public class SynBlock implements Runnable{
	private static int ticketNum=10;

	private boolean flag=true;
	

	@Override
	public void run() {//run 不可以throws异常。
		while(flag) {
			test3();	
		}
		
	}
	
	//尽可能锁定合理的范围。
	//双重检测,主要是为了确定临界值的情况
public  void test3() {
	
	if(ticketNum<=0) {//考虑的是没有票的情况。
		flag=false;
		return;
	}
	//当多个线程运行到此处时,临界值1,只有一个线程进入同步块,其他的线程在外面等待,当进去的线程执行到
	//ticketNum--,所以ticketNum就为0,外面等待的就可以直接return,从而提高了性能。
	
		synchronized(this) {
			if(ticketNum<=0) {//考虑的是只剩下最后一张票的情况。
				flag=false;
				return;
			}
		try {
			Thread.sleep(100);//会出现数据异常的情况。
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"--->"+ticketNum--);
		}
	}
	
	
	
	
	//同步块。
	//因为我们需要判断的是ticketnum和flag,但是锁对象只能是一个
	//所以向上找,即是SynBlock,所以就是this
	//不可以单独锁ticketNum不行,因为ticketNum是一个会变的,因此锁不住
	//在进行给对象加锁时,要锁的对象是一个不变的量。
	public  void test2() {
		
		synchronized(this) {
		if(ticketNum<=0) {
			flag=false;
			return;
		}
		try {
			Thread.sleep(100);//会出现数据异常的情况。
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"--->"+ticketNum--);
		}
	}
	
	
	
	
	//同步方法
	//线程安全,同步
	//成员方法所得就是this,就是调用该方法的对象。
	//锁的是this对象的资源。
	public synchronized void test1() {
		if(ticketNum<=0) {
			flag=false;
			return;
		}
		try {
			Thread.sleep(100);//会出现数据异常的情况。
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"--->"+ticketNum--);
	}
	
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//一个资源
		
		System.out.println(Thread.currentThread().getName());//该线程即是main方法。
		
		SynBlock ts=new SynBlock();
		//多个代理(也即是意味着并发)
		new Thread(ts,"1").start();
		new Thread(ts,"2").start();
		new Thread(ts,"3").start();
		new Thread(ts,"4").start();
		
	}

}
发布了43 篇原创文章 · 获赞 11 · 访问量 2548

猜你喜欢

转载自blog.csdn.net/weixin_43328816/article/details/104415722