线程数据共享
问题:5个售票点,共同售卖100张门票。
分析:5个售票点对应5个线程,
使用Thread
错误案例:
private static int tickets = 100;
private static int count = 0;
public void run() {
while (tickets > 0) {
if (tickets > 0) {
try {
//给售票点生成随机等待时间
Thread.sleep(new Random().nextInt(1000));
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
tickets--;
System.out.println(Thread.currentThread().getName() + "\t当前票号:" + count);
}
}
}
//测试类代码
public static void main(String[] args) {
//Thread创建线程,5窗口售100票
new Ticketoffice01().start();
new Ticketoffice01().start();
new Ticketoffice01().start();
new Ticketoffice01().start();
new Ticketoffice01().start();
}
分析:这里结果看似正确,实则在每一次线程就绪时生成一个随机等待时间,但是有可能会连续生成两个一样的等待时间,此时线程会发生争抢资源,可能导致输出的票号乱序。
这里需要用到一个关键字synchronized——同步锁。
private static int tickets = 100;
private static int count = 0;
public void run() {
while(tickets >= 0) {
synchronized(Ticketoffice01.class) {
if(tickets <= 0) {
break;
}
try {
sleep(new Random().nextInt(500));
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName() + "这是第" + tickets-- + "号票");
}
}
}
//测试类代码
public static void main(String[] args) {
//Thread创建线程,5窗口售100票
new Ticketoffice01().start();
new Ticketoffice01().start();
new Ticketoffice01().start();
new Ticketoffice01().start();
new Ticketoffice01().start();
}
synchronized(类名.class)将类做为锁。对象公同使用一个锁时,线程会阻塞。