java - 通过 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() 的内容,以避免锁定渲染线程。但是我想知道是否有更优雅的方式来做到这一点。
解决方案
是的,这会阻塞渲染线程,因为只有在没有读锁被持有的情况下才能获取写锁。
在这种情况下,使用锁是多余的。解决方案是声明mData
volatile:
private volatile Data mData;
推荐阅读
- wpf - 启用“仅我的 xaml”时,如何使我的控件出现在 Visual Studio 的实时可视化树工具窗口中?
- javascript - 如何忽略字符串的前两个字符
- bash - 如何使用 vim 以交互方式编辑 shell 脚本变量?
- elasticsearch - 7.5 版之前的 Elastic Search 加权平均 aggs
- docker - Docker 版本文档链接
- ruby-on-rails - 升级到 Rails 6 导致 CentOS 上的 SQLite 依赖错误
- amazon-web-services - openshift 集群中的 Elasticsearch 问题“无法获取节点锁,尝试使用锁 ID [0] [[/usr/share/elasticsearch/data]]”
- background - 如何在 React Native Base 中制作圆形标签?
- vb6 - VB6 应用程序的执行不一致。某些用户成功,运行时错误 481 Invalid Picture for others
- flutter - Flutter StreamBuilder 中的 Stream 是否会自行更新?