精华内容
下载资源
问答
  • 通过短信向全国500万会计人员发送短信,这时高峰期会有10万多用户同时在线答题。解决办法是:1、使用了LVS + Nginx四台机器进行负载均衡2、用了Spring + Redis实现4台Tomcat的Session共享3、答...
    高并发是指较多用户同时访问服务。高并发可以由多线程实现,但是多线程不代表就是高并发。
    在会计汇有个投票调查项目,是和财政部合作的,会计人员进行填写完调查结果后,将获得5个学分。通过短信向全国500万会计人员发送短信,这时高峰期会有10万多用户同时在线答题。解决办法是:
    1、使用了LVS + Nginx四台机器进行负载均衡
    2、用了Spring + Redis实现4台Tomcat的Session共享
    3、答题页面静态化,
    4、用户提交答卷后临时存放在Redis中,直接返回结果。
    5、定时器每隔一段时间将Redis数据保存到MySQL
    展开全文
  • 一直以来有个疑问? Spring中的bean不是单例模式吗?为什么那么客户端访问...如果该逻辑涉及到对该单例状态(成员变量)的改变,就会有线程安全的问题。 Spring使用ThreadLocal来解决线程安全问题,每个线程去执行业

    一直以来有个疑问?
    Spring中的bean不是单例模式吗?为什么那么多客户端访问同一个接口不会出现线程安全问题?
    其实:

    1. spring单例模式指的是在内存中只实例化一个类的对象。确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
    2. 当多个用户同时请求一个接口服务的时候,容器会给每一个请求分配一个线程,这时候多个线程会并发执行该请求所对应的业务逻辑。如果该逻辑涉及到对该单例状态(成员变量)的改变,就会有线程安全的问题。
    3. Spring使用ThreadLocal来解决线程安全问题,每个线程去执行业务代码的时候,都会去内存申请临时变量,这样就不会涉及变量并发访问冲突的问题。
    4. 一般的 Web 应用划分为展现层、服务层和持久层三个层次,在不同的层中编写对应的逻辑,下层通过接口向上层开放功能调用。在一般情况下,从接收请求到返回响应所经过的所有程序调用都同属于一个线程。

    那JVM是如何实现线程的独立内存空间?

    • 每当启用一个线程时,JVM就为他分配一个Java栈,栈是以帧为单位保存当前线程的运行状态。某个线程正在执行的方法称为当前方法,当前方法使用的栈帧称为当前帧,当前方法所属的类称为当前类,当前类的常量池称为当前常量池。当线程执行一个方法时,它会跟踪当前常量池。
    • 每当线程调用一个Java方法时,JVM就会在该线程对应的栈中压入一个帧,这个帧自然就成了当前帧。当执行这个方法时,它使用这个帧来存储参数、局部变量、中间运算结果等等。
    • Java栈上的所有数据都是私有的。任何线程都不能访问另一个线程的栈数据。所以我们不用考虑多线程情况下栈数据访问同步的情况。
    展开全文
  • 高并发是指较多用户同时...通过短信向全国500万会计人员发送短信,这时高峰期会有10万多用户同时在线答题。解决办法是: 1、使用了LVS + Nginx四台机器进行负载均衡 2、用了Spring + Redis实现4台Tomcat的Sessio...

    高并发是指较多用户同时访问服务。高并发可以由多线程实现,但是多线程不代表就是高并发。

    在会计汇有个投票调查项目,是和财政部合作的,会计人员进行填写完调查结果后,将获得5个学分。通过短信向全国500万会计人员发送短信,这时高峰期会有10万多用户同时在线答题。解决办法是:

    1、使用了LVS + Nginx四台机器进行负载均衡

    2、用了Spring + Redis实现4台Tomcat的Session共享

    3、答题页面静态化,

    4、用户提交答卷后临时存放在Redis中,直接返回结果。

    5、定时器每隔一段时间将Redis数据保存到MySQL。

    转载于:https://www.cnblogs.com/huigee/p/9748442.html

    展开全文
  • 使用ssm开发的一个售票系统,现在需要售票,如果在同一时刻有多用户在进行购票,访问票务产品库存数量减一的接口,不会出现一张票被卖次的情况。需不需要添加线程安全,加锁之类的
  • 但是用得时候也存在一些安全隐患,比如同一块资源可能线程共享,也就是线程可能会访问同一块资源,这样出现一些数据错乱和数据安全的问题.下面我们就看一些例子. 存钱取钱案例 比如我现在1000元,...

    首先看一下问题引出,先看一些经典的问题.

    多线程的隐患

    首先我们利用多线程的话肯定是好处多多,因为我们可以同时去做一些事情,大大的提高了效率.像我们下载视频的时候就可以同时下载多个视频,这样是节省了很多时间,用户体验也会更好.但是用得时候也会存在一些安全隐患,比如同一块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源,这样会出现一些数据错乱和数据安全的问题.下面我们就看一些例子.

    存钱取钱案例

    比如我现在有1000元,同时有2个线程去处理,一个线程是取钱100元,一个线程是存钱100元,我制作了一张示意图如下:

    存钱取钱示意图

    我们从上面的图应该很清楚,存100、取100的最终结果就是还是剩余1000元,但是看我们上面的示意图,最终结果要么是900要么是1100,这就与1000的结果对不上,所以很明显用多线程是会存在隐患,下面我们用代码演示一下上面的结果:

    卖票案例

    这个和上面的稍微有点差别,因为上面的是2个操作,而卖票呢,它是1个操作.同样的比如我现在有1000张票,同时有2个线程去处理卖票,一个线程是一个线程卖票100张,另一个线程也是卖票100张,同时操作的话,也会出现异常,我制作了一张示意图如下:

    我们同样的也可以用代码演示一下效果:

    上面的两个,大家可以试试.接下来针对上面的问题,我们就引出了今天的主角,线程同步技术

    线程同步技术

    解决方案:使用线程同步技术 (同步,就是协同步调,按照预定的先后次序进行运行),我们先来看下线程同步技术有哪些方案:线程同步方案最常见的技术就是:加锁.大概方案如下(大致这么多方案,当然还有其他的)

    OSSpinLock (自旋锁)

    os_unfair_lock (互斥锁)

    pthread_mutex (互斥锁、递归锁)(里面3种类型,目前只说2种对我们有用的)

    dispatch_queue (DISPATCH_QUEUE_SERIAL)

    NSLock

    NSRecursiveLock

    NSCondition

    NSConditionLock

    @synchronized

    以上的这些都是可以做到线程同步方案,我会一个一个介绍,并且介绍它们的优缺点,性能怎么样,我们怎么去选择等等.我们就以上面的例子讲解.

    OSSpinLock (自旋锁)

    OSSpinLock 叫做 "自旋锁", 等待锁的状态会处于忙等( busy-wait )状态,一直占用着CPU内存.头文件导入<libkern/OSAtomic.h>,而且这个锁是过期锁,iOS10以后就过期了,但是我们还是来看看,因为面试中可能会遇到,用法如下:

    初始化锁:OSSpinLock  spinLock = OS_SPINLOCK_INIT;

    加锁: OSSpinLockLock(&_spinLock);

    解锁: OSSpinLockUnlock(&_spinLock);

    我们先看卖票:

    我是加锁和解锁了,为什么上面的代码还有问题,有发现原因的吗?这是因为SpinLock是局部变量,所以我们进去都是初始化了一把新锁,这把锁并没有被使用过,是达不到加锁的目的.所以所有的线程都是用同一把锁才能达到加锁的目的.请看下面代码:

    确实是剩下85张,没有问题.原理是这样,每次执行saleTicket都会进入  //加锁: OSSpinLockLock(&_SpinLock) 这个代码,第一次进来是正常给_SpinLock加锁,第二次进来的时候,发现_SpinLock已经被人加了锁,它会在这边等待,等待这把锁被解锁,解锁完了以后然后它再去加锁,就这样依次进行,就保证了里面的那段代码同时只有一个线程在处理.这就解决了线程同步的问题.

    接下来我们就看存钱和取钱的问题.存钱、取钱是2个操作,我们是用同一把锁还是2把锁?思考了这个问题我们就知道怎么做了,因为存钱和取钱是不能同时进行,所以我们就用同一把锁即可(2把锁是有问题的大家可以自己试试),请看下面的代码,我们验证一下:

    自旋锁"忙等"状态是怎么等呢?忙等就是一直忙碌,而且还在等待,类似这样while(锁还没有解开),就会一直执行,占用cpu,直到锁被放开.而且OSSpinLock是已经过期了,而且目前已经不再安全,可能会出现优先级反转的问题.

    下面说一下线程的调度问题

    其实你看上面的图,如果随着时间的推移,操作系统把时间给thread1一点时间,再给thread2一点时间,再给thread3一点时间,而且这个时间周期非常短,就这样一直非常快的切换,这样下来给我们的感觉就是同时执行.这就是实现多线程的一个方案.也就是多线程的原理,我们也可以说这是时间片轮转调度算法.调用进程或者线程都是用这套算法

    还有个就是线程的优先级问题,比如thread1的优先级比较高,那么操作系统就会给thread1多一点时间去执行.其他的线程就少一点时间去执行.这样的话,我们使用自旋锁就会存在一个优先级反转的问题.比如thread1优先级非常高,thread2优先级很低.首先是thread2先进去加锁,thread1再进来就会等thread2解锁,由于thread1的优先级非常高,CPU就把大量的时间给了thread1,此时可能导致thread2没有时间执行解锁,thread1就会一直执行等待,有点死锁的感觉.

    这样大家想一想:如果优先级高的不是忙等,而是休眠,休息就不会占用CPU,那不就是解决了这个问题.

    os_unfair_lock (互斥锁)

    os_unfair_lock用于取代不安全OSSpinLock,是从iOS10开始支持.

    从底层调用看,等待os_unfair_lock锁的线程会处于休眠状态,并非忙等(后面会证明一下)

    它的用法和OSSpinLock非常像,需要倒入头文件<os/lock.h>,用法如下:

    初始化锁:os_unfair_lock  unfairLock = OS_UNFAIR_LOCK_INIT;

    加锁: os_unfair_lock_lock(&_unfairLock);

    解锁:os_unfair_lock_unlock(&_unfairLock);

    下面我们就去看一下用法

    存钱和取钱也是一样的道理,我们可以自己试试.

    pthread_mutex (互斥锁)

    像这种pthread开头的一般都是跨平台的Windows、linux等等都是可以用的,mutex叫做"互斥锁",等待锁的线程会处于休眠状态

    其实用法都是差不多,我们先来看下怎么用,这个稍微代码多一点点

     //初始化属性

        pthread_mutexattr_t attr;

        pthread_mutexattr_init(&attr);

        pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);

        //初始化锁

        pthread_mutex_init(&_mutex, &attr);(&attr也可以传NULL,这样的话,上面的都是默认的,上面可以都不用写)

        //加锁

        pthread_mutex_lock(&_mutex);

        //解锁

        pthread_mutex_unlock(&_mutex);

        //销毁相关资源

        pthread_mutexattr_destroy(&attr);

        pthread_mutex_destroy(&_mutex);

    其中PTHREAD_MUTEX_NORMAL是锁的类型,后面会细说,先传默认PTHREAD_MUTEX_NORMAL

    先看运行结果:

    没有问题,记得销毁哈,之前说的2个锁,没有提供销毁的方法,那我们就不写,如果提供了,我们还是写一下的好!

    pthread_mutex (递归锁)

    我们再看另一种情况,请看下面的代码:

    上面这些代码会出现什么情况?死锁,会出现相互等待的情况,只会输出第一个NSLog,遇到这种情况我们怎么解决才好呢?2把不同的锁即可解决问题,就是otherMutexTest里面一把锁,otherMutexTest2里面另一把锁就可以解决了,这个我就不截图了,我们可以自己试试

    再看下面另一种情况:出现递归怎么办?如下图

    遇到上面的这种情况我们又怎么处理,如果就像截图那样的话,就会出现休眠等待.如果我们想执行下去,我们就是可以设置锁的类型来解决这个问题:一共3种类型如下

    我们只要把锁的类型换成递归锁,立刻就能解决这个问题,我们加一个递归停止条件,不然会一直运行

    还有一个注意的,这个允许重复加锁,一定是在同一个线程,如果是多个线程的话,就不行.递归锁:允许同一个线程对一把锁重复加锁.

    自旋锁、互斥锁汇编分析

    自旋锁:一直忙等,占用CPU内存,一直在执行代码;互斥锁:不等待,休眠.不执行代码.我们怎么去证明这个问题呢?我们可以从汇编实现上去证明这个问题,我们先看OSSpinLock自旋锁:

    首先我们如果用这个上面的来调试的话,是看不出来什么效果的,因为这里面都是一大段一大段汇编代码执行的,我们需要一句一句的执行汇编指令.就需要敲si,s是step的意思,代码一行一行的执行,如果只用s的话,就是一行oc代码执行,一行oc对应可能一大段汇编,所以我们还需要加i,i是instruction的意思是一行一行汇编指令执行,简称si. 还有个是nexti,它也是一行一行汇编指令执行,只是nexti它是遇到函数就会一下执行过去.因为我们要看函数实现,所以我们用si.

    我们再看一下,我代码是怎么写的:

    我是创建了10个线程去执行卖票,而且在卖票中间sleep(100),这样是为了,第一条线程进去,我们不管,我们主要看第二条线程在这等待的时间,到底做了什么事.所以我们主要看第二条的汇编代码.sleep(100)是为了时间长点,方便我们能看出做什么事.如果时间太短,直接第二条线程就不等待,那我们就看不到效果,请看下面的结果

    从上面的结果看,进入OSSpinLockLock函数,它会一直在81aef那里一直循环执行,这是外循环,我们所说的自旋锁就是这样,一直循环执行,占用CPU内存.一旦有人放开这把锁就会条件循环结束,不会再执行循环.

    接下来我们看看互斥锁pthread_mutex

    查找的方法和上面的一样,我就截图最关键的图即可,请看下面:

    执行到最后,直接是callsys,调用系统的方法,是不是类似我之前说的runloop里面的休眠的方法,而且我们知道休眠是任何事情都不会做,不占用CPU内存,所以我们最后看到,我的模拟器立刻又弹出来了,说明确实是睡眠,不占用任何CPU内存.

    os_unfair_lock_lock我们可以用上面的方法尝试,它的结果也是互斥锁.

    由于锁内容较多,我会在接下来的博客继续介绍

    接下来我会继续努力编写其他博客,您的支持就是我最大的动力!

    如果觉得我写得对您有所帮助,请点赞关注我,我会持续更新😄

    感谢支持🙏🙏🙏!

    我是GDCoder,我们下期见!

    展开全文
  • 然而,很多人编写Servlet程序时并没 注意到多线程安全的问题,这往往造成编写的程序在少量用户访问时没有任何问题,而在并发用户上升到一定值时,就经常出现一些莫明其妙的问题。 Servlet的多线程机制 ...
  • 确实,在一开始接触的时候,不少人都会将三者混淆,误以为所谓的分布式高并发的系统就是能同时供海量用户访问,而采用多线程手段不就是可以提供系统的并发能力吗?实际上,他们三个总是相伴而生,但侧重点又不同。...
  • 确实,在一开始接触的时候,不少人都会将二者混淆,误以为所谓的高并发的系统就是能同时供海量用户访问,而采用多线程手段不就是可以提供系统的并发能力吗? 实际上,他们两个总是相伴而生,但侧重点又不同。 ...
  • 由于项目特别:只能用struts2+...在action中得到,我不知道这个东西是不是全局的变量,多人同时访问时候出现问题吗? 前端分页用的是pager-taglib ;如果问题怎么样改进下?? 补充:用户访问量不是很大;
  • 我们把那些可能线程同时操作的资源称为临界资源,加锁的目的就是让这些临界资源在同一时刻只能一个线程可以访问。这是当时在讲synchronized锁时提出的锁的概念。 数据库作为用户共享的一个资源,如何保证...
  • Stateful Session Bean 与 Stateless Session Bean ,这两种的 Session Bean都可以将系统逻辑放在 method之中执行,不同的是 Stateful Session Bean 可以记录呼叫者的状态,因此通常来说,一个使用者会有一个相对应...
  • 本书共22章,包括操作符、控制执行流程、访问权限控制、复用类、多态、接口、通过异常处理错误、字符串、泛型、数组、容器深入研究、Java I/O系统、枚举类型、并发以及图形化用户界面等内容。这些丰富的内容,包含了...
  • 18、一个用户表中一个积分字段,假如数据库中100万个用户,若要在每年第一天凌晨将积分清零,你将考虑什么,你将想什么办法解决? 107 19、一个用户具有个角色,请查询出该表中具有该用户的所有角色的其他...
  • 线程想同时访问同一个资源时,就存在资源冲突,这时,大家最直接想到的就是加锁来互斥访问,加锁会有这么几个问题: 等待资源的线程进入睡眠,发生用户态向内核态的切换,有一定的性能开销; 占用资源的线程...
  • 上次面试时,问到了当服务器启动之后,用户访问servlet时,如何解决并发问题,当时感觉并发问题好像是由web容器解决的吧,后来问到那会有多少个实例呢?这个没有印象,就说好像是一个吧,他又追问,个用户请求servlet,...
  • 项目问题并限制对问题访问,并创建用于提交新问题和合并请求的模板。 此外,在项目之间转移问题 标签 分类问题或使用描述性标签合并请求 里程碑 设置发布问题和合并请求的里程碑,并带可选的截止日期 看板...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 184
精华内容 73
关键字:

多用户访问会有线程问题吗