有两段代码,第一段是理解线程不安全,第二多是加锁的
1.没加锁的:
public class TestThread4 implements Runnable{
//票
private int ticketNum=100;
@Override
public void run() {
while(true){
if(ticketNum<=0){
break;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"---拿到了票:"+ticketNum--);
}
}
public static void main(String[] args) {
TestThread4 testThread4=new TestThread4();
//可用共同资源
new Thread(testThread4,"张三").start();
new Thread(testThread4,"李四").start();
new Thread(testThread4,"王五").start();
}
}
部分结果:
张三---拿到了票:10
李四---拿到了票:9
王五---拿到了票:7
张三---拿到了票:8
李四---拿到了票:6
张三---拿到了票:5
王五---拿到了票:5
李四---拿到了票:4
张三---拿到了票:3
王五---拿到了票:2
李四---拿到了票:1
王五---拿到了票:0
张三---拿到了票:-1
不安全分析:
1.情况一:会拿到同一张票
假设两个人都进入了while循环,都处在System.out.println(Thread.currentThread().getName()+"---拿到了票:"+ticketNum--);
输出之前,张三进了循环,但是张三没有抢占到CPU资源,接着,王五拿到第5张票以后,获得了CPU资源,执行完毕后,才轮到张三执行。
2.情况二:-1票
有多个人拿到了同一张票,在第1个减一后变为1,第二个人减一后变为0,第三个人减一后变为-1
2.加锁,线程安全的
public class TestThread4 implements Runnable{
//票
private int ticketNum=10;
Object obj = new Object();
@Override
public void run() {
synchronized (obj){
while(true){
if(ticketNum<=0){
break;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"---拿到了票:"+ticketNum--);
}
}
}
public static void main(String[] args) {
TestThread4 testThread4=new TestThread4();
//可用共同资源
new Thread(testThread4,"张三").start();
new Thread(testThread4,"李四").start();
new Thread(testThread4,"王五").start();
}
}