A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 陈欢 中级黑马   /  2012-7-28 02:43  /  2103 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

在下面的代码中定义了一个静态方法,方法内部不涉及调用外部变量,比如说实现某种功能,那么这个静态

方法在遇到多线程问题的时候是否会存在安全隐患呢? 是否属于线程安全呢,对这个理解比较模糊。


public class Test implements Runnable {  

   public static void main(String[] args) {  
         
        new Thread(new Test(), "Thread 1").start();  

        new Thread(new Test(), "Thread 2").start();  
   
     }  


public static void show() {  
        int x = 1;  
      
        if (x != 0)  

            System.out.println("输出:" + x);  
        a++;  

     }  
   
    @Override

    public void run() {  
        while (true) {  
          show();  

       }  

    }  
  
}

5 个回复

倒序浏览
安全隐患必须存在,线程所运行的方法没有进行保护。所以当多个线程同时调用一个方法时。就可能出现你在使用方法的时候,我半路杀进来也在使用。

具体保护方式参看这段代码。
  1.         public static void main(String[] args) {

  2.                 new Thread(new Runnable() {
  3.                         public void run() {
  4.                                 show();
  5.                         }
  6.                 }, "Thread 1").start();
  7.                 new Thread(new Runnable() {
  8.                         public void run() {
  9.                                 show();
  10.                         }
  11.                 }, "Thread 2").start();

  12.         }

  13.         public static void show() {
  14.                 int x = 1;
  15.                 synchronized (Main.class) {   // 进行线程保护。加锁是当前类的字节码
  16.                         if (x != 0) {
  17.                                 System.out.println("输出:" + x);
  18.                         }
  19.                         x++; // 楼主,这里是 x 吧。你写的是 a
  20.                 }
  21.         }
复制代码
回复 使用道具 举报
便于楼主理解,写了一个代码给楼主看。
  1.         public static void main(String[] args) {

  2.                
  3.                 /*
  4.                  *  为了方便楼主理解代码大部分都加有注释。
  5.                  *         楼主第一次运行程序数秒之后,观察控制台是否有错误输出。 肯定有。仔细找。
  6.                  *  
  7.                  *  
  8.                  *  之后把我打有★★★★★的这两行注释取消掉。
  9.                  *  楼主第二次运行程序数秒之后,观察控制台是否没有错误输出。肯定没有。随便找。
  10.                  *  当然,用铁道部xxx的话,就是:不保证奇迹的发生。
  11.                  *  
  12.                  *  
  13.                  *  最后。创建 init。 注意这的Xianchenganquan换成你的类名。
  14.                  *  也就是第一行代码。
  15.                  * */
  16.        
  17.                 new Xianchenganquan().init();

  18.         }

  19.         private void init() {

  20.                 // 创建Ouppter类
  21.                 final Ouppter outputer = new Ouppter();

  22.                 // 创建线程。并启动
  23.                 new Thread(new Runnable() {
  24.                         public void run() {
  25.                                 while (true) {
  26.                                         try {
  27.                                                 // 等待10毫秒
  28.                                                 Thread.sleep(10);
  29.                                         } catch (InterruptedException e) {
  30.                                                 e.printStackTrace();
  31.                                         }
  32.                                         // 线程调用同一个方法,传入内容
  33.                                         outputer.outoup("12345678901234567890123456789");
  34.                                 }
  35.                         }
  36.                 }).start();

  37.                 // 创建线程。并启动
  38.                 new Thread(new Runnable() {
  39.                         public void run() {
  40.                                 while (true) {
  41.                                         try {
  42.                                                 Thread.sleep(10);
  43.                                         } catch (InterruptedException e) {
  44.                                                 e.printStackTrace();
  45.                                         }
  46.                                         // 线程调用同一个方法,传入内容
  47.                                         outputer.outoup("ABCDEFGHIGKLMNOPQRSTUVWXYZ");
  48.                                 }

  49.                         }
  50.                 }).start();
  51.         }

  52.         // 定义一个类。Ouppter
  53.         static class Ouppter {

  54.                 // 类方法。outoup
  55.                 public void outoup(String name) {
  56.                         int len = name.length();
  57. //                        synchronized (Ouppter.class) {                   // ★★★★★★ 楼主把这句话取消注释了
  58.                                 for (int i = 0; i < len; i++) {
  59.                                         System.out.print(name.charAt(i));
  60.                                 }
  61.                                 System.out.println();
  62. //                        }
  63.                 }                                                                                        // ★★★★★★ 还有这个大括号
  64.         }
复制代码
回复 使用道具 举报
楼主突出static方法和多线程
是不是想问当静态方法结合多线程使用时是否会产生新的隐患
不会的,因为只要不在静态方法中访问外部的非静态成员
而多线程操作中对于共享资源操作做好了同步,不会产生新的问题
也就是说静态结合多线程,需要处理的都是各自的安全问题
不会因为他们的结合而产生新的安全隐患
回复 使用道具 举报
public class Thread1 implements Runnable {  
    public static void main(String[] args) {  
         
         new Thread(new Thread1(), "Thread 1").start();  

        new Thread(new Thread1(), "Thread 2").start();  
     
     }  

public static void show() {  
         int x = 1;  //这里定义的局部变量在show()方法里边所以声生命周期很短
                    //随着该函数的消失而消失,所以每次执行的时候x都是1自然当在理想的情况下输出的也都是1
          if (x != 0) //所以建议别设定成局部变量

            System.out.println(Thread.currentThread().getName()+"输出:" + x);  
         x++;  

     }
// synchronized(Thread1.class){
//if (x != 0) //所以建议在这串代码的外部加上同步锁因为是static所以用的锁是类对象
//  
//    System.out.println(Thread.currentThread().getName()+"输出:" + x);  
// x++; }
//Thread 2输出:1
//Thread 2输出:1
//Thread 2输出:1
//Thread 2输出:1
//Thread 2输出:1
//Thread 2输出:1
//Thread 2输出:1
//Thread 2输出:1
//Thread 2输出:1
//Thread 2输出:1
//Thread 2输出:1
//Thread 2?       这里就发生了问题,没有输出,我给你解释一下吧,你不是创建了两个线程
                  //对象么,所以这两个线程对象在抢夺CPU资源,而CPU将最终的执行权给谁
//                 都是随机的,如果你没有采取安全措施的话,那么当线程t1执行时进如show()方法后,有肯能
//                 当在判断完if语句后,只打印出了线程的名字后他的执行权就被t2给抢夺走了,于是t2就开始
//                 执行run()方法,这样还没等X输出出来呢就被切换到了另一个线程了,发生了安全问题
     
    @Override
    public void run() {  
         while (true) {  
           show();  

       }  

    }  
   
}

无标题.png (23.94 KB, 下载次数: 29)

无标题.png
回复 使用道具 举报
会有安全隐患的,你要同步就没事了。这个跟静态没有关系。如果是操作静态的数据,静态的数据时共享的数据,也扯不上安全问题。所以感觉你弄乱了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马