Spring annotations and synchronization locks cannot solve the synchronization problem

This article mainly introduces how to solve the problem that spring annotations and synchronization locks cannot be synchronized. It is introduced in great detail through the example code, which has a certain reference value for everyone's study or work. Friends in need can refer to it

Conclusion: if transaction and synchronization lock are used simultaneously in the method of service layer, data synchronization cannot be guaranteed.

@Service
public class ServiceImpl{

  private static Lock lock = new reentrantlock(false);

  @Transactional(rollbackFor = Exception.class)
  public void update() {
    try {
      lock.lock();
      ... ...
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      lock.unlock();
    }
  }
}

The above example cannot guarantee the consistency of data. The same is true for synchronized.

reason:

According to the AOP characteristics of spring, the transaction will be opened before the update method, and then locked. When the locked code is executed, the transaction will be committed.

Because the lock code block is executed within the transaction, the transaction has not been committed when the code block is executed. Therefore, after other threads enter the synchronized code block, the database data read is not the latest (dirty read).

Solution:

  1. Add a synchronization lock before the transaction is opened, and call the transaction adding method with the locking method

@Service
public class ServiceImpl{

  private static Lock lock = new reentrantlock(false);

  public void update1() {
    try {
      lock.lock();
      update2();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      lock.unlock();
    }
  }

  @Transactional(rollbackFor = Exception.class)
  public void uodate2() {
    ... ...
  }
}

2. Put the lock on the upper floor

@Controller
public class TestController{
  @Autowired
  private IServiceImpl serviceImpl;

  private static Lock lock = new reentrantlock(false);

  public String test() {
    try {
      lock.lock();
      serviceImpl.update();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      lock.unlock();
    }
  }
}

@Service
public class ServiceImpl{

  @Transactional(rollbackFor = Exception.class)
  public void update() {
    ... ...
  }
}

The above is the whole content of this article. I hope it will help you in your study, and I hope you will support us a lot.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>