请关注我的微信公众号
个人微信公众号
技术交流群 (仅作技术交流):642646237
请关注我的头条号:
例子
addListener()、removeListener()和updateProgress()是同步方法,多线程可以安全地使用这些方法。
例子的问题——外星方法对多线程的隐患
updateProgress()调用了外星方法。
外星方法可以做任何事情,例如持有另外一把锁。这样一来,程序就在对加锁顺序一无所知的情况下使用了两把锁,这样就有可能发生死锁。
例子的问题——如何避免
唯一的解决思路是避免持有锁时调用外星方法。
例子的问题——如何避免——保护性复制
在遍历之前对listeners进行保护性复制(defensive copy),再针对这份副本进行遍历:
在调用外星方法时不用加锁,而且大大减少了代码持有锁的时间。长时间地持有锁将影响性能(降低了程序的并发度),也会增加死锁的可能。
保护性复制也修复了与并发无关的另一个bug——修复后如果监听器在onProgress()中调用removeListener(),将不会影响到正在进行遍历的副本。









网友评论