Are local variables to method being shared by threads? - java

This question is an extension of this question.
What if in that question AbcRunnable would have a member variable as a class which only has methods which are getting called from Runnable. E.g.
public class AbcRunnable implements Runnable
{
private final AbcSupplier supplier;
public void run() {
List<Message> messages = supplier.get();
}
}
public class AbcSupplier implements Supplier<List<Message>> {
public List<Message> get() {
List<Message> list = new ArrayList<>();
/*
Some operations on list
*/
return list
}
}
So, in this case, if 2 threads are sharing the object of AbcSupplier because we are creating only one instance of it. Then, will they also share the local variable list in there? Or they won't be?
I tried running it by myself. To me, it looked like, they are getting shared but not 100% sure.

No. Two threads running AbcRunnable.run() won't share the same instance of the list returned by AbcSupplier.get(). This is because get() creates an ArrayList instance every time it runs.
Here's a version that would cause threads to share the same list:
public class AbcSupplier implements Supplier<List<Message>> {
List<Message> list = new ArrayList<>();
public AbcSupplier() {
......
Some operations on list
......
}
public List<Message> get() {
return list;
}
}
In this case, the same AbcSupplier instance would return the same List instance.

Related

Some case-specific questions about multi-threading

Question 1.
If we consider the following class:
public class Test {
public static LinkedList<String> list;
}
How would you make getting/setting thread-safe for the variable 'list'?
I guess I could do something like this:
public class Test {
private static LinkedList<String> list;
public static synchronized LinkedList<String> getList() {
return new LinkedList<>(list);
}
public static synchronized void setList(LinkedList<String> data) {
list = new LinkedList<>(data);
}
}
Question 2.
But how thread-safe is this? Would I have to initialize a new list each time to ensure other copies don't affect the variable?
Question 3.
If we consider this instead:
public class Test {
private static LinkedList<String> list;
public static synchronized void ManipulateList() {
// do stuff to 'list'
}
public static synchronized void ChangeList() {
// do more stuff to 'list'
}
}
where both methods 'ManipulateList' and 'ChangeList' might add or remove variables to the same list
Is this thread-safe? Does this mean that if thread 1 is accessing 'ManipulateList' then thread 2 is not able to access 'ChangeList' until thread 1 finishes accessing 'ManipulateList'?
I'm just not sure if I'm understanding the effects correctly.
Question 1.
public static LinkedList<String> list;
How would you make getting/setting thread-safe for the variable
'list'?
Avoid global [mutable] state. Just get rid of it.
Question 2.
public class Test {
private static LinkedList<String> list;
public static synchronized LinkedList<String> getList() {
return new LinkedList<>(list);
}
public static synchronized void setList(LinkedList<String> data) {
list = new LinkedList<>(data);
}
}
But how thread-safe is this? Would I have to initialize a new list
each time to ensure other copies don't affect the variable?
(I am going to assume by this you mean Test.list not the passed in data which, due to the defects of the Java collection library, is mutable itself.
So you are always accessing the list with the same lock held. You are always copying the list when dealing with the outside world. The members of the list are immutable, so you don't need any deep copying. All good.
The method have the lock held over an expensive operation not involving the variable, so we should do better here.
public static synchronized LinkedList<String> getList() {
// The `LinkedList` list points to is never mutated after set.
LinkedList<String> local;
synchronized (Test.class) {
local = list;
}
return new LinkedList<>(local);
}
public static void setList(LinkedList<String> data) {
LinkedList<String> local = new LinkedList<>(data);
synchronized (Test.class) {
list = local;
}
}
In theory, even without the change the lock needn't be held continuously for the entire copy. As it is a public lock object (but naughty, but common) data could wait on it releasing the lock temporarily. Obviously not significant here, but in real world cases it may lead to strangeness.
Slightly more obscurely, list could be made volatile and the lock elided.
Question 3.
private static LinkedList<String> list;
public static synchronized void ManipulateList() {
// do stuff to 'list'
}
public static synchronized void ChangeList() {
// do more stuff to 'list'
}
Is this thread-safe? Does this mean that if thread 1 is accessing
'ManipulateList' then thread 2 is not able to access 'ChangeList'
until thread 1 finishes accessing 'ManipulateList'?
Yes. Other than there may be waits and one of the methods could call the other, perhaps indirectly.
General notes.
Remove global [mutable] state.
Try to avoid shared mutable object (keep shared object immutable and mutable objects unshared).
Reduce the amount of code and time that locks are held for.
Copy mutable inputs and outputs.
I guess I could do something like this:
This isn't thread safe.
Specifically, the setter:
public static synchronized void setList(LinkedList<String> data) {
list = new LinkedList<>(data);
}
does not enforce that data is accessed exclusively for the duration of the setList method. As such, other threads could modify the list during the implicit iteration.
The code in question 3 is fine with respect to updates to the list, because the fact the methods are synchronized means that the list is accessed mutually exclusively, and the effects of one method invocation are visible to subsequent invocations.
But it's not entirely safe, because nefarious code can acquire (and hold onto) the monitor of Test, which could lead to a deadlock.
You can fix this specific issue by having an explicit monitor that can only be acquired inside the class:
class Test {
private final Object obj = new Object();
public static void ManipulateList() {
synchronized (obj) { ... }
}
public static void ChangeList() {
synchronized (obj) { ... }
}
}
Anything that subclasses your Test class could break your synchronization scheme because subclasses could directly access the list without the method-synchronization - either by subclassing your Test class or through reflection.
public class MyTestClass extends Test {
// blah...
public static changeTheList() {
this.list.add("Bypasses synchronization through direct access to the list.");
}
}
A better solution for synchronization is to initialize your list with a synchronized wrapper, like this:
public class Test {
private static LinkedList<String> list = Collections.synchronizedList(new LinkedList<>());
public static synchronized LinkedList<String> getList() {
return list;
}
public static synchronized void setList(LinkedList<String> newList) {
list = newList;
}
}
In the second snippet, you can now safely sub-class your Test class and access the list in a thread-safe manner because the list itself is synchronized.
You other option is to mark your Test class as final but you would still need to fix your implementation (you re-initialize the list in your getter's & setter's which is not a good idea).
Also -- I might suggest you look at some tutorials regarding synchronization -- a couple of suggestions:
https://www.baeldung.com/java-synchronized-collections
https://howtodoinjava.com/java/collections/arraylist/synchronize-arraylist/

Update ArrayList by passing argument in Java

I am trying to up create and update an ArrayList by passing an argument, so that I will end up with a list of say 10 names; however, the current function doesn't seem to be working - any ideas pls?
public String addClient(String name) {
ArrayList<String> myList = new ArrayList<String>();
myList.add(name);
return myList;
}
You are creating a new ArrayList every time you call it. This means that every time you call this method you create a brand new Collection and only store the one client in it. You need to keep a reference of a single collection around and keep adding to that. You can do that by passing in the array you want to add it to:
public List<String> addClient(String name, List<String> array) {
array.add(name);
return array;
}
This doesn't seem like a useful function, so I'm guessing this is within a class. So this might be the approach you want:
/**
* Class is not Thread Safe
*/
public class ClientList {
private final ArrayList<string> clients;
public ClientList() {
this.clients = new ArrayList<>();
}
public void addClient(String client) {
this.clients.add(client);
}
public List<String> getClients() {
// Note: Never give a reference to the internal objects of the class
// as that means someone outside this class can own a reference to it
// and can update the object without you knowing (by not going
// through this class)
Collections.unmodifiableList(this.clients);
}
}
This is what you need to do:
ArrayList<String> myList = new ArrayList<String>();
public void addClient(String name) {
myList.add(name);
}
If you create a list inside the method, it will only have one value, and will go away once method execution finishes (unless it's returned). Have a look at different scopes here. You should create a list at a class level and add the elements into it.
Also, method does not need to return anything, so it's better to change the type to void.
The problem with your approach is that everytime you call the method addClient a new ArrayList will be created.
I think this will work for you :
static ArrayList<String> myList;
public static void main(String[] args) {
myList = new ArrayList<>();
}
public void addClient(String name){
myList.add(name);
}

ArrayList initializing

Hey guys I just have a quick question about initializing an arraylist
This is just a small piece of code I'm doing
public class OrderManager {
ArrayList<Order>orders = new ArrayList<Order>();
public OrderManager() {
}
public OrderManager(ArrayList<Order> orders) {
orders = new ArrayList<Order>();
}
using a variable orders, and then declaring orders = new correct? Or is this going to be two different instances and when I try to add things to it its not going to work?
Or since OrderManager is going to take an arraylist does it even make sense?
I haven't tested it yet, I just started writing this code and have ran into this problem before where I couldn't add to the list properly and believe it was because of a error similar to this just checking to try and get it right to start with.
public class OrderManager {
private ArrayList<Order>orders;
public OrderManager() {
this(new ArrayList<>());//call constructor
}
public OrderManager(ArrayList<Order> orders) {
this.orders = orders;
}
.
.
//more methods here for example getters and/or setters for orders
}
This is the proper way. Also consider using List rather than ArrayList cause in future if you want not to be ArrayList and for example be LinkedList you don't have to modify this class. Programming to an interface concept.
So your class would look like:
public class OrderManager {
private final List<Order>orders;
public OrderManager() {
this(new ArrayList<>());//call constructor or doing nothing is another option
}
public OrderManager(List<Order> orders) {
this.orders = orders;
}
public List<Order> getOrders(){
return orders;
}
public void addOrder(Order order){
orders.add(order);
}
}
What you are currently doing is assigning a new, empty ArrayList instead of taking the one given.
You should either do this:
public class OrderManager {
private final List<Order> orders;
public OrderManager() {
orders = new ArrayList<Order>();
}
public OrderManager(final List<Order> orders) {
this.orders = orders;
}
Which will take the reference to the List passed into the constructor. Changes to the List from outside the class will affect the List inside the class.
A more common way is to make a "defensive copy" using the copy constructor
public class OrderManager {
private final List<Order>orders;
public OrderManager() {
orders = new ArrayList<Order>();
}
public OrderManager(final List<Order> orders) {
this.orders = new ArrayList<Order>(orders);
}
Now the class has a copy of the List passed in so it will be independent of the original List.
Your second constructor is wrong.
It should be:
public OrderManager(ArrayList<Order> orders) {
this.orders = orders;
}
Constructor is what used to create a new object and initialize its class variables.
When you use new you are calling a class constructor.
There are cases when one constructor can be called from another. It's done when the calling constructor initializes a larger set of variables and uses other constructor to initialize a sub-set (so not to repeat the same code). At such cases you use this with a proper signature.

Clear Singleton instance in Java

I have a Singleton class to save the state of an application's module.
This class simply have a lot of class variables with setters and getters :
public class ModuleState{
private static ModuleState instance;
private A a;
private B b;
private C c;
..
..
..
..
private ModuleState (){}
public ModuleState getInstance(){
if(instance==null)
instance=new ModuleState();
return instance;
}
}
At a precise moment of the application lifecycle, i have the need to CLEAR the module's state. What i do now is to reset ALL the variables in ModuleState by a clearAll() method like this:
public void clearAll(){
a=null;
b=null;
c=null;
..
..
}
My question is the following : there is a cleaner method to do this reset? Possibly clearing the singleton instance itself, without resetting every class variable?
The problem with this approach is that i may have the need to add a new class variable to the ModuleState. In this case i must remember to add a line in the clearAll() method to reset the new variable.
What about ...
public static volatile ModuleState instance = null;
public static void reset() {
instance = new ModuleState();
}
p.s.: as per discussion below: in a multithreaded environment it's very important to synchronize the access on the instance because the JVM is allowed to cache its value. You can use volatile as shown above. Thanks to all!
Cheers!
no, this approach is perfectly acceptable. you are of course synchronizing access to these state objects in some way, right? otherwise you risk someone seeing a half-cleared config object.
another thing you could do to future-proof yourself against any extra state added in the future is store all of your state in a HashMap, for example, instead of individual fields. this way, clear()ing the hashmap ensures that all state is wiped and adding any extra state in the future becomes safer
You need to maintain the same object instance, in order to comply with the Singleton pattern, so your approach makes sense: altering the members.
However, if you wanted to clean it up a little bit, why not just have an internal list, like:
ArrayList<Object> members = new ArrayList<Object>();
// If it actually is Object, there's no need to paramaterize.
// If you want, you can actually make the members implement a common interface,
// and parameterize the ArrayList to that.
Another Option would be to have a HashMap, that binds the key word to the member.
HashMap<String,Object> members = new HashMap<String,Object>();
// Again, same parameterization rules apply.
For an ArrayList or a HashMap, the clearAll method might look like this:
public class ModuleState()
{
public void clearAll()
{
members.clear();
}
}
This method won't need to change.
May be this can help you:
public class SingletonBean {
private static SingletonBean instance = new SingletonBean();
private static Object privateMutex = new Object();
private SingletonBean() {
//to prevent instantiation
}
public class ObjectsContainer {
private Object A;
private Object B;
private Object C;
public Object getA() {
return A;
}
public void setA(Object a) {
A = a;
}
public Object getB() {
return B;
}
public void setB(Object b) {
B = b;
}
public Object getC() {
return C;
}
public void setC(Object c) {
C = c;
}
}
private ObjectsContainer objectsContainer;
private void resetObjectsContainer() {
objectsContainer = new ObjectsContainer();
}
public static SingletonBean getInstance() {
return SingletonBean.instance;
}
public static void clearAll() {
synchronized (privateMutex) {
SingletonBean.getInstance().resetObjectsContainer();
}
}
public static ObjectsContainer getObjectsContainer() {
synchronized (privateMutex) {
return instance.objectsContainer;
}
}
}
public class SomeClass {
public void someMethod() {
SingletonBean.getObjectsContainer().getA();
}
}
Make an inner class to hold the fields, then replace that instance when you want to reset. The write to the field would make the change to all three fields essentially atomic.
public class ModuleState {
private static volatile ModuleState instance;
private static class Values {
A a;
B b;
C c;
}
private volatile Values values = new Values()(
private ModuleState (){}
public ModuleState getInstance(){
if (instance==null) {
synchronized (ModuleState.class) {
if (instance==null) {
instance = new ModuleState();
}
}
}
return instance;
}
public synchronized A getA() {
return values.a;
}
public synchronized void reset() {
values = new Values();
}
By the way, your null checking initialization code was not threadsafe. I fixed that too.
Note that to make this work, you must make the reference to values volatile and synchronize all access to it, otherwise (due to the java memory model) other threads than the one that calls reset() may see the old reference.

What is the correct way to synchronize a shared, static object in Java?

This is a question concerning what is the proper way to synchronize a shared object in java. One caveat is that the object that I want to share must be accessed from static methods. My question is, If I synchronize on a static field, does that lock the class the field belongs to similar to the way a synchronized static method would? Or, will this only lock the field itself?
In my specific example I am asking: Will calling PayloadService.getPayload() or PayloadService.setPayload() lock PayloadService.payload? Or will it lock the entire PayloadService class?
public class PayloadService extends Service {
private static PayloadDTO payload = new PayloadDTO();
public static void setPayload(PayloadDTO payload){
synchronized(PayloadService.payload){
PayloadService.payload = payload;
}
}
public static PayloadDTO getPayload() {
synchronized(PayloadService.payload){
return PayloadService.payload ;
}
}
...
Is this a correct/acceptable approach ?
In my example the PayloadService is a separate thread, updating the payload object at regular intervals - other threads need to call PayloadService.getPayload() at random intervals to get the latest data and I need to make sure that they don't lock the PayloadService from carrying out its timer task
Based on the responses, I refactored to the following:
public class PayloadHolder {
private static PayloadHolder holder;
private static PayloadDTO payload;
private PayloadHolder(){
}
public static synchronized PayloadHolder getInstance(){
if(holder == null){
holder = new PayloadHolder();
}
return holder;
}
public static synchronized void initPayload(){
PayloadHolder.payload = new PayloadDTO();
}
public static synchronized PayloadDTO getPayload() {
return payload;
}
public static synchronized void setPayload(PayloadDTO p) {
PayloadHolder.payload = p;
}
}
public class PayloadService extends Service {
private static PayloadHolder payloadHolder = PayloadHolder.getInstance();
public static void initPayload(){
PayloadHolder.initPayload();
}
public static void setPayload(PayloadDTO payload){
PayloadHolder.setPayload(payload);
}
public static PayloadDTO getPayload() {
return PayloadHolder.getPayload();
}
...
Is this approach legitimate? I am also curious if it is better to do it this way or using the AtomicReference approach mentioned by Hardcoded ...?
- I am keeping an instance of PayloadHolder on PayloadService simply to keep a reference to the PayloadHolder class active in the jvm for as long as the PayloadService is running.
Your code should look like this:
public static void setPayload(PayloadDTO payload){
synchronized(PayloadService.class){
PayloadService.payload = payload;
}
}
public static PayloadDTO getPayload() {
synchronized(PayloadService.class){
return PayloadService.payload ;
}
}
Your original code wouldn't have worked even if the methods weren't static. The reason being is you were synchronizing on the payload instance that you were changing.
Update, a response to johnrock comment:
Locking the whole class is only a problem if you have other synchronized static blocks that you want to run currently. If you want to have multiple independent locked section then I suggest you do something like this:
public static final Object myLock = new Object();
public static void setPayload(PayloadDTO payload){
synchronized(myLock){
PayloadService.payload = payload;
}
}
public static PayloadDTO getPayload() {
synchronized(myLock){
return PayloadService.payload ;
}
}
Or, if you require a more complex concurrency pattern look at java.util.concurrent which has many pre-built classes to aid you.
You could, as mentioned in other posts, synchronize on the class or on an explicit monitor.
There are 2 other ways, if we assume that your are using the sychnronize only for thread-safe getting and setting of the property: volatile and AtomicReference.
volatile
The volatile keyword will make access to the variable atomic, meaning that reading and assigning the variable won't be optimized by the CPUs local registers and are done atomically.
AtomicReference
The AtomicReference is a special class at the java.util.concurrent.atomic package, which allows atomic access to a variable-like reference. It is very similiar to volatile, but gives you some additional atomic operations, like compareAndSet.
Example:
public class PayloadService extends Service {
private static final AtomicReference<PayloadDTO> payload
= new AtomicReference<PayloadDTO>(new PayloadDTO());
public static void setPayload(PayloadDTO payload){
PayloadService.payload.set(payload);
}
public static PayloadDTO getPayload() {
return PayloadService.payload.get ;
}
Edit:
Your Holder seems quite confused, since you are instantiating classes only to call static Methods. A try to get it fixed with AtomicReference:
public class PayloadHolder {
private static AtomicReference<PayloadHolder> holder = new AtomicReference<PayloadHolder();
//This should be fetched through the holder instance, so no static
private AtomicReference<PayloadDTO> payload = new AtomicReference<PayloadDTO>();
private PayloadHolder(){
}
public static PayloadHolder getInstance(){
PayloadHolder instance = holder.get();
//Check if there's already an instance
if(instance == null){
//Try to set a new PayloadHolder - if no one set it already.
holder.compareAndSet(null, new PayloadHolder());
instance = holder.get();
}
return instance;
}
public void initPayload(){
payload.set(new PayloadDTO());
//Alternative to prevent a second init:
//payload.compareAndSet(null, new PayloadDTO());
}
public PayloadDTO getPayload() {
return payload.get;
}
public void setPayload(PayloadDTO p) {
payload.set(p);
}
}
public class PayloadService extends Service {
private final PayloadHolder payloadHolder = PayloadHolder.getInstance();
public void initPayload(){
payloadHolder.initPayload();
}
public void setPayload(PayloadDTO payload){
payloadHolder.setPayload(payload);
}
public PayloadDTO getPayload() {
return payloadHolder.getPayload();
}
}
My question is, If I synchronize on a static field, does that lock the class the field belongs to similar to the way a synchronized static method would? Or, will this only lock the field itself?
No, it just lock in the object itself ( the class attribute not the whole class )
Is this a correct/acceptable approach ?
You could probably take a look at the java.util.concurrent.lock package.
I don't really like synchronizing on a class attribute, but I guess that's just a matter of teste.
Synchronize on another static object that does not change:
public class PayloadService extends Service {
private static PayloadDTO payload = new PayloadDTO();
private static final Object lock = new Object();
public static void setPayload(PayloadDTO payload){
synchronized(lock){
PayloadService.payload = payload;
}
}
public static PayloadDTO getPayload() {
synchronized(lock){
return PayloadService.payload ;
}
}
Is this a correct/acceptable approach ?
No, the reason for this is that you should never synchronize on an variable/field that can change its value. That is, when you synchronize on PayloadService.payload and set a new PayloadService.payload, then you are violating a golden rule of synchronization.
You should either synchronize on the class instance or create some arbitrary private static final Object lock = new Object() and synchronize on that. You will have the same effect as synchronizing on the class.
There is a major part of functionality in this class which isn't posted which contributes to whether or not this approach is thread-safe: how do you access the PayloadDTO instance from the other parts of this class where it is used?
If you are providing methods which could swap in another instance for payload while another thread is running code which uses the payload object, then this is not thread safe.
For example if you have a method execute() which does the main work of this class and invokes methods on payload, you need to make sure that one thread cannot change the payload instance with the setter method while another thread is busy running execute().
In short, when you have shared state, you need to synchronize on all read and write operations on the state.
Personally I don't understand this approach and would never take it - providing static methods to allow other threads to re-configure a class smells like a violation of separation of concerns.

Categories