在java中声明方法synchronized的权衡?
每当我试图从线程 A 中杀死线程 B 时(通常,有时它会起作用),我的 Android 应用程序中都会遇到线程因某些未知原因而锁定的问题。我猜想这是因为我的一些方法在没有同步的情况下跨线程进行调用。我使取消方法和许多本质上是事件处理程序的方法同步,并使一些共享变量变得易失性,一切正常。
我不知道我添加的 20 个奇怪的 volatile/synchronized 声明中哪一个真正解决了问题,这让我思考“我应该关心吗?它有效,不要弄乱它!”
所以,我的问题是:声明同步方法或原始易失性方法是否需要权衡?如果不需要的话,是否有理由避免这些声明?
编辑
有问题的线程是正在接收/发送流数据的蓝牙连接,因此 ASyncTask 和其他工作线程类型解决方案无法正常工作。它们被设计用于执行有限的任务并在完成后终止。有些(例如 ASyncTask)还会增加大量开销,从而导致应用程序崩溃。对于像这样连续运行的线程,使用线程仍然是最好的方法。
我正在使用 android Service 来生成和管理线程,所以我在这方面遵循 Android 设计范例。
I had a problem with a thread locking up for some still unknown reason in my Android App whenever I tried to kill Thread B from Thread A (usually, sometimes it worked). I guessed that it was because some of my methods were making calls across the threads without being synchronized. I made the cancel method and a lot of methods that were essentially event handlers synchronized and made a few shared variables volatile and everything worked.
I don't know which among the 20 odd volatile/synchronized declarations I added actually solved the problem, and that got me thinking "Should I care? It works don't mess with it!"
So, my question is: Is there any trade off associated with declaring a method synchronized or a primitive volatile? Is there any reason to avoid these declarations if they are not needed?
Edit
The thread(s) in question is a Bluetooth connection that is receiving/sending streaming data, so ASyncTask and other worker thread type solutions don't work well. They are designed for performing a finite task and terminating when done. Some, like ASyncTask, also add a lot of overhead that simply kills the app. For continuously running threads like this, using a Thread is still the best way to do it.
I am using an android Service to generate and manage the threads so I am following Android design paradigms in that respect.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
根据我的经验,使用synchronized(object){...} 访问特定对象,在尽可能细粒度的级别上进行锁定通常更容易,而且性能通常更高。另外,如果您必须同时获取多个锁,请务必确保始终以相同的顺序获取它们。
静态方法有其自身的一大块奇怪之处需要担心;同步实例方法只会同步到该实例,而不同步到整个类,因此如果您需要在实例方法中同步到这两个实例,则需要执行诸如synchronized(this.class){.. .} 同样,尽管如果您应用上述内容,实际上您只需对在特定方法中访问的静态字段执行synchronized() 即可。
另外需要注意的是,一般来说,您不想生成自己的线程,而应该使用系统预先存在的机制进行线程管理(例如用于持续工作队列的 ThreadPoolExecutor 或用于异步 UI 更新的 AsyncTask)。 ThreadPoolExecutor 往往性能更高(并且可以更好地利用多核设备),但如果它要对 UI 执行操作,则必须做一些额外的工作;另一方面,AsyncTask 往往速度稍慢且重量级更大,但它也在 UI 线程中运行其 onPostExecute 回调。
In my experience it's generally easier and often more performant to do your locking at as fine-grained a level as possible, using synchronized(object){...} for accesses to a particular object. Also, if there are several locks that you have to acquire at the same time, ALWAYS make sure that you're always acquiring them in the same order.
Static methods have their own chunk of weirdness to worry about; a synchronized instance method will only be synchronized to that instance, not to the class as a whole, and so if you need to synchronize to both in an instance method you'll need to do something like synchronized(this.class){...} as well, although if you're applying the above, really you'd just be doing synchronized() over the static fields that you're accessing in the particular method.
As another note, in general you don't want to be spawning your own threads, and instead should use the system's pre-existing mechanisms for thread management (such as ThreadPoolExecutor for ongoing work queues or AsyncTask for asynchronous UI updates). ThreadPoolExecutor tends to be more performant (and can better leverage multi-core devices), but you have to do some extra work if it's going to do things to the UI; AsyncTask, on the other hand, tends to be a bit slower and more heavyweight but it also runs its onPostExecute callback in the UI thread.
如果它有效,暂时不要修复它:),但对于下一个项目,您应该考虑使用 异步任务。 开发指南。我认为在 Android 环境中,性能影响并不是真正值得关注的问题,但复杂性、可读性和未来的可维护性可能是一个问题(取消/终止线程、许多共享变量)。
If it work don't fix it for now :), but for the next project you should consider using AsyncTask. Dev Guide. I don't think the performance impact isn't of real concern in Android context, but the complexity, readability and future maintainability can be a problem (cancel/kill thread, many shared variables).