java中多线程的安全问题以及解决办法



publicstaticvoid main(String[] args) {

   

   //show2();

   show();

}

publicstaticvoid show(){

   Appleap=newApple("ljf1");

   Thread t1=new Thread(ap);

   Thread t2=new Thread(ap);

   Thread t3=new Thread(ap);

   Thread t4=new Thread(ap);

   t1.start();

   t2.start();

   t3.start();

   t4.start();

}

publicclass Appleimplements Runnable{

   private Stringname;

   public Apple(String name){

      this.name=name;

   }

   privateintticket=100;

   

   publicvoid run(){

   

      while(ticket>0){

      

          try { //A,b,c,d,A线程的ticket=1,判断之后合法,进入执行sleeepbticket此时也=1

             //然后执行sleepA获得执行权,进行了ticket--,此时为0b此时或得执行权,ticket--,后ticket-1,出现不合法的情况。

             Thread.sleep(10);

          } catch (InterruptedException e) {

             //TODO Auto-generatedcatch block

             e.printStackTrace();

          }

          System.out.println("name:"+name+":"+(ticket--));

      }

      }

   

 

}

截取部分结果:

name:ljf1:16
name:ljf1:15
name:ljf1:14
name:ljf1:13
name:ljf1:12
name:ljf1:11
name:ljf1:10
name:ljf1:9
name:ljf1:8
name:ljf1:7
name:ljf1:6
name:ljf1:5
name:ljf1:4
name:ljf1:3
name:ljf1:2
name:ljf1:1
name:ljf1:0
name:ljf1:-1
name:ljf1:-2



1原因:多条语句来操作同一线程的共享资源时,一个线程对多条语句只执行了一部分,还没有执行完,另外一个线程参与来执行,导致共享资源的错误。


解决的办法:使用同步代码块。



解决的办法:使用同步代码块。


Synchronized(同步对象){


需要被同步的代码块。


}



加锁修改之后:


publicclass Appleimplements Runnable{


   private Stringname;


   public Apple(String name){


      this.name=name;


   }


   privateintticket=100;


   Objectobj=newObject();


   publicvoid run(){


     synchronized(obj){


      while(ticket>0){


      


          try { //A,b,c,d,A线程的ticket=1,判断之后合法,进入执行sleeepbticket此时也=1


             //然后执行sleepA获得执行权,进行了ticket--,此时为0b此时或得执行权,ticket--,后ticket-1,出现不合法的情况。


             Thread.sleep(10);


          } catch (InterruptedException e) {


             //TODO Auto-generatedcatch block


             e.printStackTrace();


          }


          System.out.println("name:"+name+":"+(ticket--));


      }


      }


   }


 


}



总结:对象如同锁,持有锁的线程可以在同步中执行,没有持有锁的线程即使获取cpu的执行权也进不去。


同步的前提:1.必须要有两个或者两个以上的线程。2必须是多个线程使用同一个锁。必须保证同步中只能有一个线程在运行。


好处:解决了多线程的安全问题。


弊端:多个线程需要判断锁,较为消耗资源。

 

2.

第二种方式:使用同步函数:函数都需要被对象调用,函数都有一个所属对象的引用,this

同步函数所使用的锁是this

 public static void main(String[] args) {
  Apple apple=new Apple("ljf");
  new Thread(apple).start();
  new Thread(apple).start();
  new Thread(apple).start();
  new Thread(apple).start();
 }

public class Apple implements Runnable{
private int ticket=100;
private String name;
public Apple(String name) {
 super();
 this.name=name;
}
public  void run(){
 
 while(ticket>0){
  
   try {
  Thread.sleep(10);
 } catch (InterruptedException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 }
 System.out.println(name+">>"+ticket--);
 }
 
 
}
}

出现不和谐的情况:

ljf>>100
.

.

.
ljf>>12
ljf>>11
ljf>>13
ljf>>10
ljf>>9
ljf>>8
ljf>>7
ljf>>6
ljf>>5
ljf>>2
ljf>>3
ljf>>4
ljf>>1
ljf>>-2
ljf>>-1
ljf>>0

给方法加上同步修饰符,使其变为同步函数:

public class Apple implements Runnable{
private int ticket=100;
private String name;
public Apple(String name) {
 super();
 this.name=name;
}
public synchronized void run(){
 
 while(ticket>0){
  
   try {
  Thread.sleep(10);
 } catch (InterruptedException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 }
 System.out.println(name+">>"+ticket--);
 }
 
 
}

结果为:

.

.

.

ljf>>9
ljf>>8
ljf>>7
ljf>>6
ljf>>5
ljf>>4
ljf>>3
ljf>>2
ljf>>1


 

 

 





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值