关于JAVA多线程中抢火车票出现抢到负数票的问题解决办法及synchronized正确使用

关于多线程中抢火车票出现抢到负数票的问题

解决方法

  • java给我们提供了具体的方法:就是同步代码块。
  • 格式:synchronized(对象){ //这个对象可以是任意的对象
  •        //需要被同步执行的语句
    
  •    }
    
  • 同步的原理:其实就是将需要同步的代码进行了封装,然后在将封装的代码块之上加了一把锁。
  • 同步的好处:解决了多线程的安全问题。
  • 同步的弊端:会降低性能。
  • 切记:
  • 当一个线程获得对象锁正在执行时,其他线程可以调用非synchronized方法
  • 所以synchronized在不同位置可能出现不同状况
  • 下面我给出了synchronized在不同位置的方法

public class WEeb12306 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		WEb12306 web = new WEb12306();

		Thread t1 = new Thread(web,"路人甲");
		Thread t2 = new Thread(web,"路人乙");
		Thread t3 = new Thread(web,"路人丁");
		t1.start();
		t2.start();
		t3.start();
	}

}

class WEb12306 implements Runnable {
	private int num = 10;
	private boolean flag = true;

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while (flag) {
			test1();
		}
	}
/**
 * 线程不安全,当一个线程获得对象锁正在执行时,其他线程可以调用非synchronized方法
 * 几个线程都以经过了判断条件后执行,导致数据错误
 */
	public void test6() {
		if (num <= 0) {
			flag = false;
			return;
		}
		synchronized (this) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "抢到了" + num--);
		}
	}
/**
 * 线程不安全,锁定的资源错误,应该锁定对象
 */
	public void test5() {
		synchronized ((Integer) num) {
			if (num <= 0) {
				flag = false;
				return;
			}
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "抢到了" + num--);
		}
	}
/**
 * 线程错误锁定的范围错误
 */
	public void test4() {
		synchronized (this) {
			if (num <= 0) {
				flag = false;
				return;
			}
		}
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "抢到了" + num--);
		}
	

	public void test3() {
		synchronized (this) {
			if (num <= 0) {
				flag = false;
				return;
			}
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				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) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName() + "抢到了" + num--);
	}
/**
 * 线程错误,几个线程共享资源造成数据可能重复
 */
	public void test1() {
		if (num <= 0) {
			flag = false;
			return;
		}
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName() + "抢到了" + num--);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值