线程 多线程同步加锁说明

看代码,看注释,

一般都是用 synchronized(this){  代码块 }, 其中注意体会this到底代表的是谁, 并注意 加锁的代码块的范围别太小造成跑出的数据异常。

 

 

public class SynDemo01 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		//真实角色
		Web12306 web= new Web12306();
		//代理, 这两个代理都是针对 同一个真实对象 web 进行操作的,这样在 synchronized(this)的时候才会保证加锁正确。
		Thread t1 =new Thread(web,"zhangsan");
		Thread t2 =new Thread(web,"lisi");
		//启动线程
		t1.start();
		t2.start();

	}

}


/**
 * 线程安全的类   线程安全 需要等待 这就是效率低的说法的来源 
   加锁下,范围不能太大 太大效率低  太小锁不正确 , 并且加锁对象也要对,否则达不到加锁目的
 * @author Administrator
 *
 */
class Web12306 implements Runnable {
	private int num =10;
	private boolean flag =true;
	@Override
	public void run() {
		while(flag){
			test5();
		}
	}
	// 加锁范围太小 造成数据异常
    // 跑出结果中 有 lisi抢到了-1
	public void test6(){
	   	
		if(num<=0){
			flag=false; //跳出循环
			return ;
		}
		 //a  b  c 	
		synchronized(this){  //  
			try {
				Thread.sleep(500); //模拟 延时
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
		}
	}
	
	//线程不安全  锁定资源不正确
    	/**
lisi抢到票了,还剩下 0 张
zhagnsan抢到票了,还剩下 0 张
	 */
	public void test5(){
		//a  b  c
		synchronized((Integer)num){// 锁错对象了   一般锁定最多的还是锁对象 
			if(num<=0){
				flag=false; //跳出循环
				return ;
			}
			try {
				Thread.sleep(500); //模拟 延时
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
		}
	}
	
	
	
	//锁定范围不正确 线程不安全
    /**
	 * zhagnsan抢到票了,还剩下 -1 张
	 */
	public void test4(){
		//   c  1
		synchronized(this){
			//b
			if(num<=0){
				flag=false; //跳出循环
				return ;
			}
		}
		// b
		try {
			Thread.sleep(500); //模拟 延时
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
	}//a -->1
	
	
	
	//线程安全  锁定正确
	public void test3(){
		//a  b  c
		synchronized(this){// this 表示这份资源,  只有多个线程在使用 同一个Web12306类的对象时,才会进行加锁,eg:线程1 线程2 同时操作Web12306类的对象1,这两个线程在抢夺ticket时,哪个线程先进来就加锁
			if(num<=0){
				flag=false; //跳出循环
				return ;
			}
			try {
				Thread.sleep(500); //模拟 延时
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
		}
	}
	//线程安全  锁定正确
	public synchronized void test2(){
		if(num<=0){
			flag=false; //跳出循环
			return ;
		}
		try {
			Thread.sleep(500); //模拟 延时
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
	}
	
	
	//线程不安全
    	/**
	lisi抢到票了,还剩下 0 张
	zhagnsan抢到票了,还剩下 -1 张
	lisi抢到票了,还剩下 -2 张
	 */
	public void test1(){
		if(num<=0){
			flag=false; //跳出循环
			return ;
		}
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
	}
}

猜你喜欢

转载自chengjianxiaoxue.iteye.com/blog/2401170