什么时候需要担心线程安全?
在哪些情况下需要担心静态方法是否线程安全?
例如,如果我有不接触任何静态类级别变量的静态实用函数,那么该方法是否已经是线程安全的?如果我有一个触及静态类变量的静态方法,那么该方法是否可能不是线程安全的?
提前致谢。
What are some situations where you need to worry about whether a static method is thread safe?
For example, if I have static utility function that doesn't touch any static class level variables, is that method already thread safe? If I have a static method that does touch static class variables, is that method potentially not thread safe?
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
大多数时候 - 重要的是您的方法是否是可重入。像这样的事情是可重入的,因为一切都是局部变量,并且每个线程都会收到自己的副本:
仍然有一些事情需要注意。如果您将一个对象传递给该方法,并且该方法会改变该对象,并且在该方法完成之前您在不同的线程上再次调用相同的方法,但使用相同的对象,那么您就会遇到问题。
主要问题还是变量是否可变。如果您只读取不可变对象,那么可能不会有任何问题。
如果您调用一个方法并且不确定它是否是可重入的并且文档没有说明,那么最好假设它不是。
Most of the time - what matters is if your method is reentrant. Something like this is reentrant because everything is local variables and each thread receives its own copy:
There are still some things to be careful of. If you pass in an object to the method and the method mutates the object and before the method completes you call the same method again on a different thread but with the same object, then you have a problem.
The main issue again is if the variables are mutable. If you are only reading from immutable objects then there may not be any problem.
If you call a method and you are not sure if it is reentrant and the documentation doesn't say, it's best to assume that it isn't.
如果您在静态方法中仅使用局部堆栈变量,则无需担心。 java.lang.Math.min(int, int) 就是这种方法的一个很好的例子。但是,如果您接触任何共享静态变量或具有状态(也称为不可变)的对象,则必须使用同步。
If you using only local stack variables in static method then there is no reason to worry. java.lang.Math.min(int, int) is good example of such method. But in case if you touching any shared static variables, or objects which do have state (aka not immutable) then you have to use synchronization.
每当有多个线程访问相同资源时,您就必须担心线程安全。
如果您的静态方法直接或间接地使用与其他线程相同的资源,即使这些资源不是静态类变量,它也可能是不安全的。
You have to worry about thread safety whenever you have more than one thread accessing the same resources.
Your static method might be unsafe if it is using the same resources as other threads -- directly or indirectly -- even if those resources are not static class variables.
如果没有访问可变资源(例如类变量),则它是线程安全的 - 但是,您必须确保您的方法不会调用访问任何可变资源的任何其他方法。
It is thread-safe if no mutable resources, such as, class variables are accessed -- however, you have to make sure that your method does not call any other methods that access any mutable resources.
每当有多个线程访问相同的资源时,您就必须担心线程安全,并且这些资源不是一成不变的。
You have to worry about thread safety whenever you have more than one thread accessing the same resources, and those resources are not immutable.
如果您有一个方法写入在多个线程之间共享的任何状态(例如,静态变量或多个线程使用的任何对象),那么该方法需要担心线程安全,并且读取任何共享状态的任何方法也是如此。
If you have a method that writes to any state that's shared across multiple threads (for example, static variables, or any objects that multiple threads use), then that method needs to worry about thread-safety, and so do any methods that read any of that shared state.
如果至少有一个可以被多个线程访问的入口点,则线程安全就成为一个问题。
如果一段代码被多个线程访问并调用其他方法/类/等,那么所有这些代码树都会变得脆弱。
来自《Java并发实践》:
围绕任务执行组织程序的第一步是识别合理的任务边界。理想情况下,任务是独立的活动:不独立的工作
取决于其他任务的状态、结果或副作用。独立性有利于并发,因为如果存在独立的任务,则可以并行执行
足够的处理资源。
例如,如果您正在编写一个隔离的servlet,保证由单个线程执行,则不必担心。但是,如果您编写一个由不同 servlet 使用的静态实用程序,则必须使其能够处理多线程访问。
Thread safety becomes a concern if there is at least a single entry point which can be accessed by multiple threads.
If a piece of code is accessed by multiple threads and is calling other method/class/etc., then all this code tree becomes vulnerable.
From "Java concurrency in practice":
The first step in organizing a program around task execution is identifying sensible task boundaries. Ideally, tasks are independent activities: work that doesn’t
depend on the state, result, or side effects of other tasks. Independence facilitates concurrency, as independent tasks can be executed in parallel if there are
adequate processing resources.
For example, if you are writing an isolated servlet, which is guaranteed to be executed by a single thread, you don't have to worry. But if you write a static utility which is used by different servlets, then it has to be made to handle multi-threaded access.