关于多线程中抢火车票出现抢到负数票的问题
解决方法
- 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--);
}
}