上一篇写到了JAVA初步认识线程 ,现在就说说自己对线程同步及死锁的认识。
线程的同步,是为了避免多个线程访问相同的数据对象时,对数据造成破坏。
下面模拟多个售票员销售同一列车的票。
一.同步
package thread;
public class MyThread implements Runnable{
private int ticket=5;
@Override
public void run(){
for(int i=1;i<=100;i++){
this.sale();
}
}
private void sale(){
if(ticket>0){
try {
Thread.sleep(1000);//卖票耗时模拟
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"卖出票 "+(ticket--));
}
}
}
package thread;
public class ThreadClient {
public static void main(String[] args) {
MyThread t1=new MyThread();
for(int i=0;i<10;i++){
new Thread(t1,"售票员"+(i+1)).start();
}
}
}
运行结果:
售票员1卖出票 4 售票员3卖出票 5 售票员5卖出票 3 售票员2卖出票 2 售票员4卖出票 1 售票员6卖出票 0 售票员8卖出票 -1 售票员10卖出票 -2 售票员7卖出票 -3 售票员9卖出票 -4 售票员1卖出票 -5 售票员3卖出票 -6 售票员5卖出票 -7 售票员2卖出票 -8
看运行结果,居然出现了负数,这明显不符合实际。简单分析下。
(1)假如售票员1查看ticket,发现ticket=1,还可以继续出售,但卖票需要填写一些数据什么的,需要话费时间。
(2)售票员1还在填写票据,1号票还没卖出。此时售票员2也查看了下ticket,发现ticket=1,他认为还可以继续出售(他不知道售票员1准备出售1号票)他也准备填写票据了。
(3)在售票员2在填写出售1号的数据时,售票员1完成了填写出售1号票的数据,并将它出售了,ticket=0了,没票出售了(但是售票员2不知道)
(4)售票员2填写完数据了,让电脑打印票,这是才发现票上面写的居然是0了
这种情况就是所谓的线程不安全。那么可以使用synchronized,对出售票的动作进行加锁,在同一个时间点,只允许一个人在卖票。
package thread;
public class MyThread implements Runnable{
private int ticket=5;
@Override
public void run(){
for(int i=1;i<=100;i++){
this.sale();
}
}
private synchronized void sale(){
if(ticket>0){
try {
Thread.sleep(1000);//卖票耗时模拟
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"卖出票 "+(ticket--));
}
}
}
package thread;
public class ThreadClient {
public static void main(String[] args) {
MyThread t1=new MyThread();
for(int i=0;i<10;i++){
new Thread(t1,"售票员"+(i+1)).start();
}
}
}
运行结果
售票员2卖出票 5 售票员2卖出票 4 售票员9卖出票 3 售票员7卖出票 2 售票员7卖出票 1
运行结果符合实际了。
二、死锁
使用synchronized可以解决同步问题,但是如果使用不当,会发生死锁问题。
画画需要笔和纸。张三和李四同时想画画,张三拿到了笔,李四拿到了纸。张三在等李四给纸他,李四在等张三给笔他。于是他们两人都在等待。这就是死锁了。
package thread;
public class Pane {
public String toString(){
return "神奇的七彩笔.........";
}
}
package thread;
public class Paper {
public String toString(){
return "白花花的画纸......";
}
}
package thread;
public class DeadLockTest {
public static void main(String[] args) {
DrawPicture zs=new DrawPicture("张三");
DrawPicture ls=new DrawPicture("李四");
new Thread(zs).start();
new Thread(ls).start();
}
}
运行结果
李四得到了白花花的画纸...... 张三得到了神奇的七彩笔.........
程序打印了上面两个结果后,就卡住了(是2个线程都在等待,进入了堵塞状态)。张三和李四谁也不能完成画画。。。。都在等待对方,给资源。