首页 > 解决方案 > 通过 ReadWriteLock 或 synchronize(this) 锁定会阻塞渲染线程吗?

问题描述

通过 ReadWriteLock 或 synchronize(this) 锁定会阻塞渲染线程吗?

例如,我在无法更改代码的加载器之间编写适配器;

class LoaderAdapter implements Loader {

 private AnotherLoader.Callback callback = new AnotherLoader.Callback() {
   // Called on render thread
   public void onLoaded(Data data) {
     if (mData.equals(data)) {
       return;
     }

     mData = data;

     notifyListeners();
   }
 };

 private final AnotherLoader loader = ...

 private Data mData;

 // Called on render thread
 @Override
 public start() {
  loader.start();
 }


 // Called on background thread
 @Override
 public List<Items> getContent() {
   //iterate over contents
   return processor.process(mData);
 }
}

我不认为这是线程安全的,因为 mData 是在渲染线程上写入的,但读取来自后台线程。

为了解决这个问题,我添加了一个 ReadWriteLock;

class LoaderAdapter implements Loader {

 private AnotherLoader.Callback callback = new AnotherLoader.Callback() {
   // Called on render thread
   public void onLoaded(Data data) {
     lock.writeLock().lock();
     
     try {
       mData = data;
     } finally {
      lock.writelock().unlock();
     }
   }
 };

 private final AnotherLoader loader = ...
 private final ReentrantReadWriteLock lock ....

 private Data mData;

 // Called on render thread
 @Override
 public start() {
  loader.start();
 }


 // Called on background thread
 @Override
 public List<Items> getContent() {
     lock.readLock().lock();
     
     try {
       return processor.process(mData);
     } finally {
      lock.readLock().unlock();
     }
 }
}

现在问题是在渲染线程上调用了 onLoaded(),而我将调用 .lock()。这会阻塞渲染线程并可能会降低渲染速度吗?

有没有办法处理这个问题,而在我无法改变的两个班级之间工作?我想到的一种选择是在 BG 线程上运行 onLoaded() 的内容,以避免锁定渲染线程。但是我想知道是否有更优雅的方式来做到这一点。

标签: javamultithreadingconcurrencyjava-threads

解决方案


是的,这会阻塞渲染线程,因为只有在没有读锁被持有的情况下才能获取写锁。

在这种情况下,使用锁是多余的。解决方案是声明mDatavolatile:

private volatile Data mData;

推荐阅读