夢の殇

每天进步一点点,努力做到知其然知其所以然

JAVA线程同步与死锁

         上一篇写到了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个线程都在等待,进入了堵塞状态)。张三和李四谁也不能完成画画。。。。都在等待对方,给资源。

 

 
 
 
 
 
 
 
 

 

阅读更多
版权声明: https://blog.csdn.net/dream_broken/article/details/8869631
文章标签: JAVA 同步 死锁
个人分类: 多线程
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭