欢迎光临
我们一直在努力

一种常见的并发编程场景的处理

对于并发编程,大家想到总是多线程之间对等的临界资源竞争。然而经常会遇到下面这样的场景:

守护线程提供一个临界资源,多个子线程会并发改写该临界资源。大部分时候(99.9%的时间),主线程是不会干涉各个线程之间的竞争的,通常只要该临界资源自己内部处理好同步即可。但是偶尔主线程也会干预一下该临界资源,比如做一些统计,做一个快照,或者复制数据然后清空等。这个操作通常会耗时比较长,并且在此期间不希望有人改写临界资源。如果,主线程与各个子线程使用同样的锁或者synchronized同步,那么在主线程没有作该操作时,各个子线程之间会因为竞争而阻塞,这个阻塞开起来是没有必要的。

这里介绍一个利用volatile变量的特性解决该问题。试图在性能和数据保护上面达到最大平衡。Atomic变量采用的是寄存器变量实现的。用两个变量标志map表当前的状态。而不必在后台线程和众多业务线程之间加锁或者同步,由于在多数情况下volatile变量的性能优于锁。这里只以map表举例,其他保证线程安全的数据结构也适用。

试想,在addOneRecord方法和getAndClearAllRecords方法之间引入一个锁或者synchronized,那么每两个业务线程在添加数据的时候都要竞争,而这个竞争是不必要的。因为,只有在后台线程调用getAndClearAllRecords时,这个锁才有意义。这里引入两个寄存器变量,能有效降低一些锁竞争的问题。当然这里只是拿concurrenthashmap来举一个例子,也许在doSomeThingWithMap方法中根本没有什么需要独占整个map表的,那么整个同步机制都不需要了,只要map表自身的同步即可。

/**
 * 用于标志长时间独占表的线程是否正在工作。
 */
 private AtomicBoolean closed = new AtomicBoolean(false);
 /**
 * 用于标志当前的数据表是否正在插入数据。
 */
 private AtomicInteger busy = new AtomicInteger();
 /**
 * 用于存储数据的表格。
 */
 private ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>();
 /**
 * 多个线程会并发调用该接口向
 * map表中插入数据。
 * @param key
 * @param value
 */
 public void addOneRecord(String key, String value)
 {
 /**
 * 大多数时候,该循环都不会占用性能资源。
 */
 while (closed.get())
 {
 waitAMoment();
 }
 if (map != null)
 {
 /**
 * 用一个同步变量在各个线程中计数。
 */
 busy.getAndIncrement();
 map.put(key, value);
 busy.getAndDecrement();
 }
 }
 /**
 * 后台线程会定期处理map表中的数据。
 */
 public void getAndClearAllRecords()
 {
 synchronized (this)
 {
 /**
 * 先将closed标志设置,以便独占该map表; 
 * 避免操作过程中被修改。
 */
 closed.set(true);
 while (busy.get() != 0)
 {
 waitAMoment();
 }
 doSomeThingWithMap(map);
 closed.set(false);
 }
 }
 private void doSomeThingWithMap(ConcurrentHashMap<String, String> map)
 {
 // TODO Auto-generated method stub
 }
 private void waitAMoment()
 {
 // TODO Auto-generated method stub
 }

总觉得分析这个问题有点纠结的感觉,其实用java,这点性能损失是可以忽略不计的。并且外层两个寄存器变量的读写并不一定比加锁性能好,而且在外层加锁的情况下,map表自身的锁竞争就不存在了,实际也只有1个锁在起作用,似乎问题没有那么糟糕。不管怎么样,这个工作感觉还是有一些意义的,总归是利大于弊吧。

 收藏 (0) 打赏

您可以选择一种方式赞助本站

支付宝扫一扫赞助

微信钱包扫描赞助

未经允许不得转载:英协网 » 一种常见的并发编程场景的处理

分享到: 生成海报
avatar

热门文章

  • 评论 抢沙发

    • QQ号
    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址

    登录

    忘记密码 ?

    切换登录

    注册

    我们将发送一封验证邮件至你的邮箱, 请正确填写以完成账号注册和激活