`
lijackly
  • 浏览: 70268 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

多线程_并发访问_锁机制_servelt

阅读更多
----------------------------------------------------------------------------------------------------------------
2010-11-11
     struts1 的前端控制器是单例的,线程不安全的;每次请求都会用同一actionServlet;
     struts2 的action不是单例的,线程安全的;每次请求都会新new一个action来接收;
     Spring的IOC容器管理的bean默认是单例的;

     如果项目中整合 struts2 和 spring ,由spring来管理struts2的action,会有问题:
          1、struts2的action有状态,有自己的成员属性,所以在多线程下,肯定有问题;

    

     如何解决:
          方案1:不用单例,spring中bean的作用域设置为prototype,每个请求对应一个实例;
                         不用request,因为request作用域只适用于 WebApplicationContext环境;
                         【spring bean的作用域有5个:singleton、prototype、request、session、globalSession】
         

     【
          struts1    是单例的,但每次请求,用actionform包装数据是新的;
          struts2 不是单例的,用action来取代了s1的actionForm和action的功能,提交的数据和渲染到页面的数据都在action里,这是没法共享的。
      】


----------------------------------------------------------------------------------------------------------------
     参考:
    
     servlet /jsp 默认是以多线程模式执行的。
     servelt建立在以java多线程机制之上,生命周期由web容器负责。
          当客户端第一次请求某个servlet时,servlet容器将会根据web.xml配置文件实例化这个servlet类,当有新的客户端请求servlet时,一般不会再实例化该servlet类,也就是多个线程在使用这个实例。
          Servlet容器自动使用线程池等技术来支持系统的运行。

     servlet的线程安全问题主要是由实例变量使用不当引起的。

         






----------------------------------------------------------------------------------------------------------------
在设计并发访问的时候,要考虑什么用锁,同步


多线程安全:
     要认识java的线程安全,必须了解两个主要的点:java的内存模型、java的线程同步机制;


java内存模型:
     不同的平台,内存模型是不一样的,但是jvm的内存模型规范是统一的。java的多线程并发问题最终会反映在java的内存模型上。
     所谓线程安全是要控制多个线程对某个资源的有序访问或修改。
    
     要解决两个主要的问题:可见性和有序性。

     [
          计算机有高速缓存的存在,处理器并不是每次处理数据都是取内存的。
          JVM定义了自己的内存模型,屏蔽了底层内存管理细节,对于java开发人员,要解决的是在jvm内存模型基础上,如何解决多线程的可见性和有序性。
     ]
    
    
可见性:
       多个线程之间不能互相传递数据通信,它们之间的沟通只能通过共享变量进行。Java内存模型规定了jvm有主内存,主内存是多个线程共享的。当new一个对象的时候,也是被分配在主内存中,每个线程都有自己的工作内存,工作内存存储了主存的某些对象的副本,当然线程的工作内存大小是有限制的。
执行顺序如下:
1、从主存复制变量到当前工作内存(read and load)
2、执行代码,改变共享变量值(use and assign)
3、用工作内存数据刷新主存相关内容(store and write)
      当一个共享变量在多个线程的工作内容中都有副本时,如果一个线程修改了这个共享变量,那么其他线程应该能够看到这个被修改后的值,这就是多线程的可见性。


有序性:
     线程在引用变量时不能直接从主内存中引用,如果线程工作内存中没有改变量,则会从主内存中copy一个副本到工作内存中,这个过程为read-load,完成后线程会引用该副本。当同一线程再度引用该字段时,有可能重新从内存中获取变量副本(read-load-use),也有可能直接引用原来的副本,也就是说read,load,use顺序可以由JVM实现系统决定;

    

      线程不能直接为主存中字段赋值,它会将值指定给工作内存中的变量副本(assign),完成后这个变量副本会同步到主存储区,至于何时同步过去,根据JVM系统决定。

package thread;

/**
*
* @author Administrator
* 不用synchronized 修饰add reduce方法, 每次执行的结果是不确定的。
* 因为线程的执行顺序是不可预见的,这是java同步产生的根源。
*  synchronized关键字保证了多个线程对于同步块是互斥的,
*  这种同步手段,解决了java多线程的执行有序性和内存可见性。
*
*
*/
public class MyAccount {
     private int balance;
     
     public MyAccount(int b){
          this.balance = b;
     }
     
     public void add(int num){
          balance += num;
     }
     
     public void reduce(int num){
          balance -= num;
          
     }
     
     public static void main(String[] args){
          MyAccount account = new MyAccount(999);
          Thread addT = new Thread(new AddThread(account,10),"add");
          Thread redT = new Thread(new AddThread(account,10),"reduce");
          
          try {
               addT.start();
               redT.start();
          
               addT.join();
               redT.join();
               
          } catch (InterruptedException e) {
               e.printStackTrace();
          }
          
          System.out.println(account.balance);
     }
     
     static class ReduceThread implements Runnable{
          MyAccount account;
          int amount;
          
          public ReduceThread(MyAccount ac,int am){
               this.account = ac;
               this.amount = am;
          }
          
          public void run(){
               for(int i=0;i<2000;i++){
                    account.add(amount);
               }
          }
     }
     
     
     static class AddThread implements Runnable{
          MyAccount account;
          int amount;
          
          public AddThread(MyAccount ac,int am){
               this.account = ac;
               this.amount = am;
          }
          
          public void run(){
               for(int i=0;i<2000;i++){
                    account.reduce(amount);
               }
          }
     }
}


synchronized(锁){
     临界区代码;    
}


对于public synchronized void add(int num)这种情况,意味着,锁就是这个方法所在的对象。同理,如果方法是public static synchronized void add(int num),那么锁就是这个方法所在的class。

     理论上,每个对象都可以作为锁,但一个对象作为锁时,应该被多个线程共享,这样才有意义,在并发环境下,一个没有共享的对象作为锁时没有意义的。(也就是一个临时变量作为锁是没有意义的。)

public class ThreadTest{ 
  public void test(){ 
     Object lock=new Object(); 
     synchronized (lock){ 
        //do something 
     } 

}

lock变量作为一个锁存在根本没有意义,因为它根本不是共享对象,每个线程进来都会执行Object lock=new Object();每个线程都有自己的lock,根本不存在锁竞争。

     每个锁对象都有两个队列,一个就绪队列,一个是阻塞队列,
     就绪队列存储了将要获得锁的线程,阻塞队列存储了被阻塞的线程,当一个线程被唤醒(notify)后,才会进入到就绪队列,等待cpu调度。
    
     当一开始线程a执行account.add方法时,jvm会检查锁对象account的就绪队列是否已经有线程在等待,如果有则表明account的锁已经被占用了,由于是第一次运行,account的就绪队列为空,所以线程a获得了锁,执行account.add方法。如果恰好这个时候,线程b要执行account.reduce方法,因为线程a已经得到锁还没有释放,所以线程b要进入account的就绪队列,等得到锁后才可以执行。
    
     一个线程执行临界区代码过程如下:
          1、获得同步锁;
          2、清空工作内存;
          3、从主存copy变量副本到工作内存;
          4、对这些变量计算;
          5、将变量从工作内存写回到主存;
          6、释放锁;
     可见,synchronized既保证了多线程的并发有序性,又保证了多线程的内存可见性;




   
         






















分享到:
评论
1 楼 jiangmin30 2012-10-15  
引用

    [*]

    [*]
            

相关推荐

    免费超全面的Java基础类型,容器,并发,IO流,面向对象,Web编程等代码总结

    多线程并发访问,同步控制 线程间通信,等待/通知机制 锁锁机制,API详解 Fork/Join 框架机制详解 Executor线程池框架简介 面向对象 泛型机制与反射原理 Proxy动态代理机制详解 从整体上观察对象 网络开发 Servlet...

    Java并发编程(学习笔记).xmind

    (1)如果设计正确,多线程程序可以通过提高处理器资源的利用率来提升系统吞吐率 (2)建模简单:通过使用线程可以讲复杂并且异步的工作流进一步分解成一组简单并且同步的工作流,每个工作流在一个单独的线程...

    SERVLET基本原理

    描述SERVLET基本原理,包括SERVLET装载、INIT()、SERVICE()、DESTORY(),以及多线程并发处理

    基于CXF+servlet整合spring接口系统

    基于spring+serlvet+CXF+servlet异步实现等融合成的开发框架,可以实现多线程和异步并发操作,采用servlet3.0自带的异步实现方式,jdk1.6版本,javaee1.6

    开涛高可用高并发-亿级流量核心技术

    19.3 多版本机制 381 19.4 异常问题 382 20 使用OpenResty开发Web服务 383 20.1 架构 383 20.2 单DB架构 384 20.2.1 DB+Cache/数据库读写分离架构 384 20.2.2 OpenResty+Local Redis+Mysql集群架构 385 20.2.3 ...

    基于JSP+Servlet的学生管理系统.zip

    它由Sun Microsystems(现在是Oracle Corporation)的James Gosling等人在1995年推出,被设计为一种简单、健壮、可移植、多线程、动态的语言。Java的主要特点和优势包括以下几个方面: 跨平台性(Write Once, Run ...

    基于jsp+servlet+javaBean的图书管理系统.zip

    它由Sun Microsystems(现在是Oracle Corporation)的James Gosling等人在1995年推出,被设计为一种简单、健壮、可移植、多线程、动态的语言。Java的主要特点和优势包括以下几个方面: 跨平台性(Write Once, Run ...

    学生信息管理系统SIMS,Java Servlet And Jsp..zip

    它由Sun Microsystems(现在是Oracle Corporation)的James Gosling等人在1995年推出,被设计为一种简单、健壮、可移植、多线程、动态的语言。Java的主要特点和优势包括以下几个方面: 跨平台性(Write Once, Run ...

    Servlet+Jsp--基于Java语言的Web宿舍管理系统.zip

    它由Sun Microsystems(现在是Oracle Corporation)的James Gosling等人在1995年推出,被设计为一种简单、健壮、可移植、多线程、动态的语言。Java的主要特点和优势包括以下几个方面: 跨平台性(Write Once, Run ...

    基于servlet+jsp+mysql+MVC模式的学生选课管理系统.zip

    它由Sun Microsystems(现在是Oracle Corporation)的James Gosling等人在1995年推出,被设计为一种简单、健壮、可移植、多线程、动态的语言。Java的主要特点和优势包括以下几个方面: 跨平台性(Write Once, Run ...

    学习Servlet+JSP写的比较完整的项目:图书管理系统.zip

    它由Sun Microsystems(现在是Oracle Corporation)的James Gosling等人在1995年推出,被设计为一种简单、健壮、可移植、多线程、动态的语言。Java的主要特点和优势包括以下几个方面: 跨平台性(Write Once, Run ...

    精品课程网,javaWeb项目,servlet+jsp,适合做毕业设计使用.zip

    它由Sun Microsystems(现在是Oracle Corporation)的James Gosling等人在1995年推出,被设计为一种简单、健壮、可移植、多线程、动态的语言。Java的主要特点和优势包括以下几个方面: 跨平台性(Write Once, Run ...

    一个基于JSP+Servlet的房源出租管理系统,适合毕业设计 和 大作业.zip

    它由Sun Microsystems(现在是Oracle Corporation)的James Gosling等人在1995年推出,被设计为一种简单、健壮、可移植、多线程、动态的语言。Java的主要特点和优势包括以下几个方面: 跨平台性(Write Once, Run ...

    Java学生课程成绩教师信息-管理系统【JavaWeb】Servlet+Mysql+Jsp+Tomcat.zip

    它由Sun Microsystems(现在是Oracle Corporation)的James Gosling等人在1995年推出,被设计为一种简单、健壮、可移植、多线程、动态的语言。Java的主要特点和优势包括以下几个方面: 跨平台性(Write Once, Run ...

    一个基于JSP+Servlet的网上书店系统,可以用做大作业和毕业设计.zip

    它由Sun Microsystems(现在是Oracle Corporation)的James Gosling等人在1995年推出,被设计为一种简单、健壮、可移植、多线程、动态的语言。Java的主要特点和优势包括以下几个方面: 跨平台性(Write Once, Run ...

    Java全方面面试题,很全

    javaWeb,java基础,java异常,jsp&servlet,JVM,Linux,多线程并发,集合容器 springboot框架,数据结构,数据库,算法 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意...

    Middleware:攀登之路..

    多线程 并发线程的问题 多线程 可运行,可调用,线程 线程本地 易挥发,指令重排序 同步原理与应用 原子操作的实现原理 并发编程的内存模型 多线程的应用 Java中的锁 Java的并发容器 不安全 线程池 执行者 MySQL ...

    java面试题,180多页,绝对良心制作,欢迎点评,涵盖各种知识点,排版优美,阅读舒心

    【多线程】线程池原理和运行机制 83 【多线程】线程池对任务的处理 85 【多线程】线程池的状态 86 线程池的状态说明 86 各个状态之间的转换 86 【多线程】什么是线程池?如果让你设计一个动态大小的线程池,如何设计...

    JMeter Manual

    Apache Jmeter 是一个100%...2. 完全多线程,允许通过多个线程并发取样和单独的线程组不同的功能同时取样。 3. 完全可移植性和100%纯JAVA。 4. 精心的GUI设计允许快速操作和更精确的计时。 5. 缓存和离线分析测试结果。

    Java并发编程实践

    1.2 创建多线程...................................................................................................................7 1.2.1 继承Thread 创建线程...............................................

Global site tag (gtag.js) - Google Analytics