设为首页 加入收藏

TOP

浅析项目中的并发 ( 二 )(二)
2017-11-13 14:55:32 】 浏览:437
Tags:浅析 项目 并发
x = y; y = t; System.out.println("x is" + x + " y is " + y); }

一个更加直观的例子便是,同一个线程中,某个方法的递归调用不应该被阻塞,所以如果要实现这个特性,简单的使用某个key作为Monitor是欠妥的,可以加入线程编号,来保证可重入。

使用可重入分布式锁的来测试计算斐波那契数列(只是为了验证可重入性):

@RequestMapping("testReentrant")
public void ReentrantLock() {
    RLock lock = redissonClient.getLock("fibonacci");
    lock.lock();
    try {
        int result = fibonacci(10);
        System.out.println(result);
    } finally {
        lock.unlock();
    }
}
int fibonacci(int n) {
    RLock lock = redissonClient.getLock("fibonacci");
    try {
        if (n <= 1) return n;
        else
            return fibonacci(n - 1) + fibonacci(n - 2);
    } finally {
        lock.unlock();
    }
}

最终输出:55,可以发现,只要是在同一线程之内,无论是递归调用还是外部加锁(同一把锁),都不会造成死锁。

可用性

借助于第三方中间件实现的分布式锁,都有这个问题,中间件挂了,会导致锁不可用,所以需要保证锁的高可用,这就需要保证中间件的可用性,如redis可以使用哨兵+集群,保证了中间件的可用性,便保证了锁的可用性、

其他特性

除了可重入锁,锁的分类还有很多,在分布式下也同样可以实现,包括但不限于:公平锁,联锁,信号量,读写锁。Redisson也都提供了相关的实现类,其他的特性如并发容器等可以参考官方文档。

新手遭遇并发

基本算是把项目中遇到的并发过了一遍了,案例其实很多,再简单罗列下一些新手可能会遇到的问题。

使用了线程安全的容器就是线程安全了吗?很多新手误以为使用了并发容器如:concurrentHashMap就万事大吉了,却不知道,一知半解的隐患可能比全然不懂更大。来看下面的代码:

public class ConcurrentHashMapTest {
    static Map<String, Integer> counter = new ConcurrentHashMap();
    public static void main(String[] args) throws InterruptedException {
        counter.put("stock1", 0);
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        CountDownLatch countDownLatch = new CountDownLatch(100);
        for (int i = 0; i < 100; i++) {
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    counter.put("stock1", counter.get("stock1") + 1);
                    countDownLatch.countDown();
                }
            });
        }
        countDownLatch.await();
        System.out.println("result is " + counter.get("stock1"));
    }
}

counter.put(“stock1″, counter.get(“stock1″) + 1)并不是原子操作,并发容器保证的是单步操作的线程安全特性,这一点往往初级程序员特别容易忽视。

总结

项目中的并发场景是非常多的,而根据场景不同,同一个场景下的业务需求不同,以及数据量,访问量的不同,都会影响到锁的使用,架构中经常被提到的一句话是:业务决定架构,放到并发中也同样适用:业务决定控制并发的手段,如本文未涉及的队列的使用,本质上是化并发为串行,也解决了并发问题,都是控制的手段。了解锁的使用很简单,但如果使用,在什么场景下使用什么样的锁,这才是价值所在。

同一个线程之间的递归调用不应该被阻塞,所以如果要实现这个特性,简单的使用某个key作为Monitor是欠妥的,可以加入线程编号,来保证可重入。

首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇SpringBoot 定时任务踩坑记录 下一篇什么是服务提供者框架

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目