问题:50个线程,先查询数据库的一个记录 t,然后对这个记录+1,最后更新到数据库

更新的时候,不允许使用 update  test_concurrent set sum =sum -1 where id=1,如果这个做就看不出来效果了,必须使用update  test_concurrent set sum =? where id=1)。

1.创建表

CREATE TABLE `test_concurrent` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`sum` bigint(20) DEFAULT NULL COMMENT '并发的和',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

2.表里只有一条记录

INSERT INTO `test_concurrent` VALUES (1, 0);

对于这种并发问题有三种解决方法

1.使用悲观锁  select for update

2.使用乐观锁 新增一个字段,查询时设置这个字段,更新时根据这个字段更新

3.update  test_concurrent set sum =? where id=1 and sum =#{t}

4.update  test_concurrent set sum =sum-? where id=1 and sum >=?   

 

总和来说:4是最好的写法。

 

并发线程代码

@Test
    public void testAdd1() {
        log.info("开始执行----------------");
        CountDownLatch latch = new CountDownLatch(50);
        
        ExecutorService executor=new ThreadPoolExecutor(10, 50, 2000, TimeUnit.SECONDS, new ArrayBlockingQueue(50));
        AtomicInteger integer=new AtomicInteger(0);
        for(int i=0;i<50;i++){
            Integer s=i;
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    //log.info("开始执行----------------{}",s);
                    service.add1(1);
                    log.info("开始执行----------------{}",s);
                    integer.incrementAndGet();
                    latch.countDown();
                }
            });
            
            
        }
        try {
            latch.await();
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        log.info("开始执行----------------{}",integer.intValue());

 注意:线程池的用法