并发编程经验总结

线程安全操作利器 - TheadLocal

ThreadLocal是编程里非常重要的一类能够简化编程的技巧性对象

  • 线程本地变量
  • 场景:每个线程一个副本
  • 不改方法签名静默传参
  • 及时进行清理

实用场景补充:

当业务代码里有一个方法需要调用一大堆其他方法(在最里层可能跨越了10个方法),最里层的方法又需要拿到在最开始这个方法里面使用过的一个变量。这时候应该怎么处理?

  1. 中间涉及到的10多个方法,每一个方法调用的时候,把他的参数上额外的加上这个变量作为参数,一层一层的传下去。(代码改动大,比较笨)
  2. 全局静态变量或者一个系统属性。(因为都是全局的,所以线程安全存在问题)
  3. ThreadLocal:在最外层调用的方法里,把我们需要传递的数据塞到一个ThreadLocal里,在最里面需要拿到数据的地方,通过ThreadLocal再拿,只要是在一个线程内。(可以类比全局静态变量,ThreadLocal即为线程内的静态变量

延展:中间跨越的着很多层,可以是框架代码。(比如中间经过了Spring的很多层,中间的框架代码不可控,就可以利用这种机制来完成)

总结:可以看做是Context模式,减少显式传递参数。

四两拨千斤 - 并行Stream

List.stream().parallel():调用线程池的一些底层实现。可查看源码。

伪并发问题

跟并发冲突问题类似的场景很多

比如浏览器端,表单的重复提交问题。解决方案:

  • 客户端控制(调用方),点击后按钮不可用,跳转到其他页。
  • 服务器端控制(处理端),给每个表单生成一个编号,提交时判断重复
    • 一个经典的比较常用的办法:用户在每次打开一个新的表单页的时候,给他生成一个随机数或者一个订单号,先分配一个数给他,同时把这个数放在服务器端这个用户的session里,这个数在页面展示出来的时候,藏在当前表单里面的一个hidden域里。提交表单的时候会把这个数带上去,跟这个表单的其他数据一块提交到服务器上来。那么服务器端就会拿提交上来的数和session里的数比一下。如果有,那这一次表单就是第一次提交的。就可以处理。同时把session里的那个数给去掉

还有没有其他办法?

分布式下锁和计数器

分布式环境下,多个机器的操作,超出了线程的协作机制,一定是并行的。

  • 例如某个任务只能由一个应用处理,部署了多个机器怎么控制?
  • 例如针对用户的限流是每分钟60次计数,API服务器有3台,用户可能随机访问到随便一台,怎么控制?(秒杀场景是不是很像?库存固定且有限。)

经验总结:

加锁需要考虑的问题?

  1. 粒度
  2. 性能
  3. 重入
  4. 公平
  5. 自旋锁(spinlock)
  6. 场景:脱离业务场景谈性能都是耍流氓

线程间协作与通信

  • 线程间共享:
    • static/实例变量()堆内存
    • Lock
    • Synchronized
  • 线程间协作
    • Thread#join()
    • Object#wait/notify/notifyAll
    • Future/Callable
    • Semaphore
    • CountDownLatch
    • CyclicBarrier

思考:不同进程之间有哪些方式通信?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值