即日起在codingBlog上分享您的技术经验即可获得积分,积分可兑换现金哦。

JAVA多线程多任务开发不安全相关疑难问题解决方案(多线程多任务开发并发同一资源)。

编程语言 blank__box 11℃ 0评论

引例:吃苹果比赛,3个人同时吃50个苹果,谁先拿到谁就吃,每个哦ing过都有编号。

问题:

多线程同时执行的时候可能出现不安全问题


当3个人同时拿到一个苹果,他们的编号就一样,当时主要看是谁先吃掉苹果


除非拿到苹果和吃掉苹果是连续同步执行,没有其他的线程干扰

方案一:

设置同步代码块(同步锁)。

synchronized(共享资源){

同步执行代码;

}


class Apple implements Runnable{
 private int num=50;
 
 public void run() {
  for(int i=0;i<50;i++){
   synchronized (this) {//!!!解决了不安全问题,这里的this表示Apple共同资源
    //同步代码块
    //——————————————————————————————————————————————
    if(num>0){
    try {
     //导致一个资源信息被多个用户同时拿到
     Thread.sleep(10);
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName()+"吃了编号为"+num+"的苹果");
    num--;
    //——————————————————————————————————————————————————
    }
   }
  }
 }
}
//Thread.currentThread().getName() 拿到当前线程的引用和名称

public class ImplementDemo {
 public static void main(String[] args) {
  Apple a=new Apple();
  new Thread(a,"A").start();
  new Thread(a,"B").start();
  new Thread(a,"C").start();
 }
}



方法二:

同步方法。

synchronized 方法名{

方法体(同步代码);

}

class Apple implements Runnable{
 private int num=50;
 
 public void run() {
  for(int i=0;i<50;i++){
  eat();
  }  
 }
 //——————————————————————————
 synchronized private void eat() {
  if (num > 0) {
   try {
    // 导致一个资源信息被多个用户同时拿到
    Thread.sleep(10);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   System.out.println(Thread.currentThread().getName() + "吃了编号为" + num + "的苹果");
   num--;
  }
 }
}
//Thread.currentThread().getName() 拿到当前线程的引用和名称

public class ImplementDemo {
 public static void main(String[] args) {
  Apple a=new Apple();
  new Thread(a,"A").start();
  new Thread(a,"B").start();
  new Thread(a,"C").start();
 }
}

————————————————————————————华丽的分割线——————————————————————————————

运用synchronized性能并不高,例如JAVA中的Stringbuilder和Stringbuffer的区别:Stringbuffer的append方法加了synchronized保证了安全性,但是性能却比Stringbuilder低,出现了两面性,所以尽量用Stringbuilder,遇到安全问题再做操作。

建议:尽量减小synchronized代码块的大小。




方法三:

锁机制。

public interface Lock

Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的
Condition 对象。 

锁是控制多个线程对共享资源进行访问的工具。通常,锁提供了对共享资源的独占访问。一次只能有一个线程获得锁,对共享资源的所有访问都需要首先获得锁。不过,某些锁可能允许对共享资源并发访问,如
ReadWriteLock 的读取锁。 



class Apple implements Runnable{
 private int num=50;
 //创建一个锁对象
 private final Lock lock = new ReentrantLock();
 public void run() {
  for(int i=0;i<50;i++){
  eat();
  }  
 }
 
 private void eat() {
  //进入代码块之后立马加锁
  lock.lock();//获取锁
  if (num > 0) {
   try {   
    System.out.println(Thread.currentThread().getName() + "吃了编号为" + num + "的苹果");
    // 导致一个资源信息被多个用户同时拿到
    Thread.sleep(10);
    num--;
   } catch (InterruptedException e) {
    e.printStackTrace();
   } finally{
    lock.unlock();
   }
  }
 }
}
//Thread.currentThread().getName() 拿到当前线程的引用和名称

public class ImplementDemo {
 public static void main(String[] args) {
  Apple a=new Apple();
  new Thread(a,"A").start();
  new Thread(a,"B").start();
  new Thread(a,"C").start();
 }
}






转载请注明:CodingBlog » JAVA多线程多任务开发不安全相关疑难问题解决方案(多线程多任务开发并发同一资源)。

喜欢 (0)or分享 (0)
发表我的评论
取消评论

*

表情