同步与死锁
在多线程的开发中,同步与死锁的概念非常重要
class MyThread implements Runnable{ private int ticket = 5 ; // 假设一共有5张票 public void run(){ for(int i=0;i<100;i++){ if(ticket>0){ // 还有票 try{ Thread.sleep(300) ; // 加入延迟 }catch(InterruptedException e){ e.printStackTrace() ; } System.out.println("卖票:ticket = " + ticket-- ); } } } }; public class SyncDemo01{ public static void main(String args[]){ MyThread mt = new MyThread() ; // 定义线程对象 Thread t1 = new Thread(mt) ; // 定义Thread对象 Thread t2 = new Thread(mt) ; // 定义Thread对象 Thread t3 = new Thread(mt) ; // 定义Thread对象 t1.start() ; t2.start() ; t3.start() ; } };
要想解决资源共享的同步操作问题,可以使用同步代码块和同步方法两种方式完成
普通代码块:直接定义在方法之中
构造块:直接定义在类中,优先于构造方法执行,可重复调用
静态块:使用static关键字声明的,优先于构造块执行,只执行一次,在类加载时执行
同步代码块:使用synchronized关键字声明的代码块
同步的时候必须指明同步的对象,一般情况下会将当前对象作为同步的对象,使用this表示
class MyThread implements Runnable{ private int ticket = 5 ; // 假设一共有5张票 public void run(){ for(int i=0;i<100;i++){ synchronized(this){ // 要对当前对象进行同步 if(ticket>0){ // 还有票 try{ Thread.sleep(300) ; // 加入延迟 }catch(InterruptedException e){ e.printStackTrace() ; } System.out.println("卖票:ticket = " + ticket-- ); } } } } }; public class SyncDemo02{ public static void main(String args[]){ MyThread mt = new MyThread() ; // 定义线程对象 Thread t1 = new Thread(mt) ; // 定义Thread对象 Thread t2 = new Thread(mt) ; // 定义Thread对象 Thread t3 = new Thread(mt) ; // 定义Thread对象 t1.start() ; t2.start() ; t3.start() ; } };
从运行结果可以发现,加入同步操作后,不会产生负数的情况,但是,程序的执行效率明显降低很多
class MyThread implements Runnable{ private int ticket = 5 ; // 假设一共有5张票 public void run(){ for(int i=0;i<100;i++){ this.sale() ; // 调用同步方法 } } public synchronized void sale(){ // 声明同步方法 if(ticket>0){ // 还有票 try{ Thread.sleep(300) ; // 加入延迟 }catch(InterruptedException e){ e.printStackTrace() ; } System.out.println("卖票:ticket = " + ticket-- ); } } }; public class SyncDemo03{ public static void main(String args[]){ MyThread mt = new MyThread() ; // 定义线程对象 Thread t1 = new Thread(mt) ; // 定义Thread对象 Thread t2 = new Thread(mt) ; // 定义Thread对象 Thread t3 = new Thread(mt) ; // 定义Thread对象 t1.start() ; t2.start() ; t3.start() ; } };
死锁:
资源共享时需要进行同步操作!
程序中过多的同步会产生死锁!
引用菲菲的一段话,就是十个人十支筷子吃饭,人要想吃饭就必须要有两支筷子,那么必须要有人放下筷子给别人使用才能吃饭,那么如果十个人都在等待着 别人放 下筷子,那么谁也吃不到饭,就出现了死锁现象。就像两个人打架,一个人在楼上喊道:“你上来!”另一个人在楼下喊道:“你下来!”一样。。。。。
例如:
class Zhangsan{ // 定义张三类 public void say(){ System.out.println("张三对李四说:“你给我画,我就把书给你。”") ; } public void get(){ System.out.println("张三得到画了。") ; } }; class Lisi{ // 定义李四类 public void say(){ System.out.println("李四对张三说:“你给我书,我就把画给你”") ; } public void get(){ System.out.println("李四得到书了。") ; } }; public class ThreadDeadLock implements Runnable{ private static Zhangsan zs = new Zhangsan() ; // 实例化static型对象 private static Lisi ls = new Lisi() ; // 实例化static型对象 private boolean flag = false ; // 声明标志位,判断那个先说话 public void run(){ // 覆写run()方法 if(flag){ synchronized(zs){ // 同步张三 zs.say() ; try{ Thread.sleep(500) ; }catch(InterruptedException e){ e.printStackTrace() ; } synchronized(ls){ zs.get() ; } } }else{ synchronized(ls){ ls.say() ; try{ Thread.sleep(500) ; }catch(InterruptedException e){ e.printStackTrace() ; } synchronized(zs){ ls.get() ; } } } } public static void main(String args[]){ ThreadDeadLock t1 = new ThreadDeadLock() ; // 控制张三 ThreadDeadLock t2 = new ThreadDeadLock() ; // 控制李四 t1.flag = true ; t2.flag = false ; Thread thA = new Thread(t1) ; Thread thB = new Thread(t2) ; thA.start() ; thB.start() ; } };
张三说了话等待李四回应,李四说了话也等待张三回应,于是。。。。。死锁了。。。。。
也就是说,死锁一般就是表示进程间互相等待对方执行,现在谁也不执行的情况。
问题描述:死锁问题应该是这样发生的。情景:两个人,一个厕所。情节:里面的人办完事了,可是忘了带纸,就给外面的人要纸,外面的人不给,于是乎,出不 来;这外面一个人有纸急冲冲的要办事,可是进不去,说里面的人,赶紧出来,可是里面的人没有纸怎么出的来。于是,就这样两个人僵持着。问题的原因在于,里 面的人等着外面的人给他纸,外面的人等着里面的人给让位,各自需要的资源被占用了,于是死锁就发生了。
public class DeadLock implements Runnable{ //设置标识符 public int flag = 1; //创建两个Object对象 static Object o1 = new Object(); static Object o2 = new Object(); //重写run方法 public void run (){ System.out.println("flag = "+flag); if(flag == 1){ //当flag的值为1时,锁定o1,睡眠5ooms,然后执行o2 synchronized(o1){ try { Thread.sleep(500); System.out.println("i am o1"); } catch( Exception e) { System.out.println("error!"); } synchronized(o2){ System.out.println("o2"); } } } if(flag == 0 ){ //当flag的值为0时,锁定o2,睡眠5ooms,然后执行o1 synchronized(o2){ try { Thread.sleep(500); System.out.println("i am o2"); } catch( Exception e) { System.out.println("error!"); } synchronized(o1){ System.out.println("o1"); } } } } public static void main(String args[]){ DeadLock dl1 = new DeadLock(); DeadLock dl2 = new DeadLock(); //为各自对象的标识符赋值 dl1.flag = 0; dl2.flag = 1; Thread t1 = new Thread(dl1); Thread t2 = new Thread(dl2); //两个线程启动,各自调用run方法,这样的话各自需要的资源被占用,死锁发生 t1.start(); t2.start(); } }
同步,,就是多线程访问同一个资源,存在安全问题,,就必须加同步就是上锁嘛,一次只能有一个线程访问一个资源,这个线程访问完出来后,别的线程才有资格去访问,不然线程的切换 会造成安全隐患。。。
死锁,,是发生在同步的基础上的,就是说 有两个以上资源,分别加了同步,然后多个线程分别访问不同资源的时候 由于每个锁里面是相互有联系的,,这几个线程就在里面 不能访问资源,就阻塞在里面了,,说的通俗点 就是占着茅坑不拉屎,,,然后外面排队的人进不去,,里面的人也出不来,,那么程序就卡在那里了,,不人为干涉,,程序不就结束的

浙公网安备 33010602011771号