• Java 线程安全问题—synchronized锁机制


    一个采用了多线程技术的应用程序可以更好地利用系统资源。其主要优势在于充分利用了CPU的空闲时间片,可以用尽可能少的时间来对用户的要求做出响应,使得进程的整体运行效率得到较大提高,同时增强了应用程序的灵活性。更为重要的是,由于同一进程的所有线程是共享同一内存,所以不需要特殊的数据传送机制,不需要建立共享存储区或共享文件,从而使得不同任务之间的协调操作与运行、数据的交互、资源的分配等问题更加易于解决。

            如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

            线程安全问题都是由全局变量及静态变量引起的。

            若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全。

            怎样解决线程安全的问题那?

             就需要java的锁机制:synchronized(同步化的)线程同步:按预定的先后次序进行运行

             例如:1.主键生成器中,每次添加一个客户t_client的值就会增1,如果多个客户添加,甲添加一个的同时乙也添加一个,这时可能导致数据的不对,或者未添加成功,所以就需要同步执行。

    [java] view plaincopy

    public static synchronized int generate(String tableName) {  

            String sql = "select value from t_table_id where table_name=? ";  

            Connection conn = null;  

            PreparedStatement pstmt = null;  

            ResultSet rs = null;  

            int value = 0;  

                conn = DbUtil.getConnection();  

                pstmt = conn.prepareStatement(sql);  

                pstmt.setString(1, tableName);  

                rs = pstmt.executeQuery();  

                value = rs.getInt("value");  

                value++; //自加  

                modifyValueField(conn, tableName, value);//写入到数据库  

            return value;  

    }  

           2.多线程下,访问数据库,可以充分利用资源,大大缩短了访问的时间,但是如果都要在连接数据库的时候都创建一个连接和每个连接都要读取配置文件,这样就大大浪费了,系统的资源,占用内存很大,很可能让系统瘫痪。

             读取配置文件只需要一个实例,如果多了就会导致系统的资源浪费。

    Synchronized主要有四种方式:

       1. sychronized method(){}

    [java] view plaincopy

    //为了保证银行账户的安全,可以操作账户的方法如下:  

    1.  public synchronized void add(int num) {    

    2.       balance = balance + num;    

    3.  }    

    4.  public synchronized void withdraw(int num) {    

    5.       balance = balance - num;    

    6.  }   

       2. sychronized (objectReference) {}

    [java] view plaincopy

    class TreadTest   {  

          public static void main(String[] args)   {  

              ThreadB b=new ThreadB();    

              b.start();  

              System.out.println("b is start....");  

                  synchronized(b)  

                  {    

                    try {  

                          System.out.println("Waiting for b to complete...");  

                            b.wait();  

                              System.out.println("Completed.Now back to main thread");  

                           }catch (InterruptedException e){}  

                  }  

                  System.out.println("Total is :"+b.total);    

          }    

    }   

     class ThreadB extends Thread  {  

          int total;    

          public void run()  {  

              synchronized(this)  {  

                  System.out.println("ThreadB is running..");  

                  for (int i=0;i<100;i++ )  {  

                          total +=i;    

                          System.out.println("total is "+total);    

                   }    

                  notify();    

              }    

          }    

    } 全局变量  

       3. static synchronized method(){}

    [java] view plaincopy

    //上面主键生成器就是public static synchronized int generate(String tableName) {}  

      4. sychronized(classname.class)

     

    注意:其中1 和2是代表锁当前对象,即一个对象就一个锁,3和4代表锁这个类,即这个类的锁


  • 相关阅读:
    学习曲线
    正则化——“偏差(bias)”与“方差(variance)”
    诊断偏差(bias)和方差(variance)
    模型选择和训练/验证/测试数据集
    运用机器学习的建议
    训练神经网络的一般步骤
    Java数组
    类型信息(反射,RTTI)
    equals(), "== ",hashcode() 详细解释
    java并发
  • 原文地址:https://www.cnblogs.com/luckForever/p/7254198.html
Copyright © 2020-2023  润新知