I would like to create a worker thread that should be shared within other sessions. Basically I want to restrict other users from doing the same process. So They will retrieve the thread via a static Instance of object thread that I created. If the thread is still alive, then they will be prompted with error.
Is there a other way to do this because I am thinking if placing a Thread object within a static is safe? I am also thinking of application context but I am not sure which is better way to do this in java?
Placing any object in a static or in any kind of shared location is not intrinsically unsafe but you need to take care with the design.
declare
static Thing t;
initialise
if ( t == null ) {
t = new Thing();
}
use
t.dosomething();
Now what happens if two threads hit the initialise block at the same time? You can get two Things created. Probably don't want that, so use synchronisation.
synchronized void intialise() {
if ( t == null ) {
t = new Thing();
}
}
what happens if two threads attempt to use the t at the same time. This depends on the promises made by Thing. If it's thread-safe no problem, otherwise your code needs to provide synchronisation
synchronized void doSomthing() {
t.doSomething();
}
I would use a lock for the static field you set so you avoid the possibility that two tasks start the process. You can store the Thread so you know when it is finished or an AtomicBoolean to flag when it is running. (Which you can also lock on)
You can have a atomic boolean to flag the status of your worker thread and return the thread only if it false.
you would need to set it to true when the worker thread is starts.
Related
I want to know if the following (contrived) example is thread safe:
public class SpringSingleton
{
private MyObject _myObject = new MyObject("hello");
public void useObject()
{
_myObject.doSomethingCool();
}
public void changeObject()
{
_myObject = new MyObject("goodbye");
}
public static void main(String[] args)
{
// Have multiple threads, some using and some changing the object
}
}
My main question is: what will happen when one thread tries to call useObject() at the same time another thread tries to call changeObject()?
Assigning a reference is an atomic operation. You can never see a half-assigned reference. So the thread calling the doSomethingCool() method will either call it on the old reference, or on the new one.
But that doesn't make the code thread-safe. You can also have visibility problems: the thread reading the reference might see an old one even though the thread has already written a new reference. To solve that problem, you need to make the field volatile, or to wrap it into an AtomicReference, or to synchronize all accesses to the field.
Also note that if you ever change the code to
_myObject.doSomethingCool();
_myObject.doSomethingElse();
then you'll have another problem: the first call might be done on the old object, and the second on the new one. If coherence is necessary between these two calls, then those two calls, as well as every other interaction with _myObject, should be wrapped into a synchronized block (using the same lock).
If one thread tries to call useObject() at the same time another thread tries to call changeObject(), then the behavior is non-deterministic, the thread calling useObject() might see the old or the new value.
Whether or not it is "safe" depends on what behavior you desire.
It might not matter to your code which value it sees, in a short period of time.
Please skip to the TLTR if you do not want to read the whole story but the question:)
I need to fix a bug in our system and I have found the bug but could not find an optimal solution for this problem.
As an illustration, what it is aimed to be done is; when there are three files to be closed and for each file, a different thread (3 threads in this example) is created and should get the id of the file and by using file's id, it should close the file.
However, the person, who programs this, did not think something genuinely. At the moment, three threads are created for three different files and they access to the method, which distributes the ids, at the same time and the method gives the id of the first file (normally, first id to first thread, second id to second thread and third id to the third thread should be given) to three threads and these three threads try to close the same file (which causes the bug).
I cannot change this structure and it should be remain as it is.
TLTR
What I try to achieve is; how can I prevent several threads from entering the same method at the same time?
I tried synchronized (and lock) strategies for this but they did not help me in this situation, because each thread has its own lock (there are several objects created).
Create a singleton.
public static final Object globalLock = new Object();
Then in your methods where you need to protect.
synchronized(globalLock){
//get your file ids.
}
Couple of ways for doing this, here are some:
Make method synchronized
public class MyClass{
public void synchronized mySynchronizedMethod(); // only single thread will be allowed to invoke this method on the SAME INSTANCE OF MyClass
public void notSynchronizedMethod();
}
Use synchronized block:
MyClass obj=new MyClass();
synchronized(obj){
// only single thread is allowed to enter that block WITH obj INSTANCE.
obj.notSynchronizedMethod():
}
Synchronize on class
MyClass obj=new MyClass();
synchronized(MyClass.class){
//single thread is allowed for this block in a scope of WHOLE CLASS LOADER so in most cases you can say it is "globally" synchronized
}
Use Semaphore
Semaphore sem=new Sempahore(1);
sem.aquire(); // Thread will aquire permit, another thread will wait
//this will be synchronized block
sem.release(); allows another thread to aquire permit
I have class with 2 synchronized methods:
class Service {
public synchronized void calc1();
public synchronized void calc2();
}
Both takes considerable time to execute. The question is would execution of these methods blocks each other. I.e. can both methods be executed in parallel in different threads?
No they can't be executed in parallel on the same service - both methods share the same monitor (i.e. this), and so if thread A is executing calc1, thread B won't be able to obtain the monitor and so won't be able to run calc2. (Note that thread B could call either method on a different instance of Service though, as it will be trying to acquire a different, unheld monitor, since the this in question would be different.)
The simplest solution (assuming you want them to run independently) would be to do something like the following using explicit monitors:
class Service {
private final Object calc1Lock = new Object();
private final Object calc2Lock = new Object();
public void calc1() {
synchronized(calc1Lock) {
// ... method body
}
}
public void calc2() {
synchronized(calc2Lock) {
// ... method body
}
}
}
The "locks" in question don't need to have any special abilities other than being Objects, and thus having a specific monitor. If you have more complex requirements that might involve trying to lock and falling back immediately, or querying who holds a lock, you can use the actual Lock objects, but for the basic case these simple Object locks are fine.
Yes, you can execute them in two different threads without messing up your class internals but no they won't run in parallel - only one of them will be executed at each time.
No, they cannot be. In this case you might use a synchronized block instead of synchronizing the whole method. Don't forget to synchronize on different objects.
I am reading Java Concurrency in Practice and kind of confused with the thread confinement concept. The book says that
When an object is confined to a thread, such usage is automatically thread-safe even if the confined object itself is not
So when an object is confined to a thread, no other thread can have access to it? Is that what it means to be confined to a thread? How does one keep an object confined to a thread?
Edit:
But what if I still want to share the object with another thread? Let's say that after thread A finishes with object O, thread B wants to access O. In this case, can O still be confined to B after A is done with it?
Using a local variable is one example for sure but that just means you don't share your object with other thread (AT ALL). In case of JDBC Connection pool, doesn't it pass one connection from one thread to another once a thread is done with that connection (totally clueless about this because I never used JDBC).
So when an object is confined to a thread, no other thread can have access to it?
No, it's the other way around: if you ensure that no other thread has access to an object, then that object is said to be confined to a single thread.
There's no language- or JVM-level mechanism that confines an object to a single thread. You simply have to ensure that no reference to the object escapes to a place that could be accessed by another thread. There are tools that help avoid leaking references, such as the ThreadLocal class, but nothing that ensures that no reference is leaked anywhere.
For example: if the only reference to an object is from a local variable, then the object is definitely confined to a single thread, as other threads can never access local variables.
Similarly, if the only reference to an object is from another object that has already been proven to be confined to a single thread, then that first object is confined to the same thread.
Ad Edit: In practice you can have an object that's only accessed by a single thread at a time during its lifetime, but for which that single thread changes (a JDBC Connection object from a connection pool is a good example).
Proving that such an object is only ever accessed by a single thread is much harder than proving it for an object that's confined to a single thread during its entire life, however.
And in my opinion those objects are never really "confined to a single thread" (which would imply a strong guarantee), but could be said to "be used by a single thread at a time only".
The most obvious example is use of thread local storage. See the example below:
class SomeClass {
// This map needs to be thread-safe
private static final Map<Thread,UnsafeStuff> map = new ConcurrentHashMap<>();
void calledByMultipleThreads(){
UnsafeStuff mystuff = map.get(Thread.currentThread());
if (mystuff == null){
map.put(Thread.currentThread(),new UnsafeStuff());
return;
}else{
mystuff.modifySomeStuff();
}
}
}
The UnsafeStuff objects itself "could be shared" with other threads in the sense that if you'd pass some other thread instead of Thread.currentThread() at runtime to the map's get method, you'd get objects belonging to other threads. But you are choosing not to. This is "usage that is confined to a thread". In other words, the runtime conditions are such that the objects is in effect never shared between different threads.
On the other hand, in the example below the object is automatically confined to a thread, and so to say, the "object itself" is confined to the thread. This is in the sense that it is impossible to obtain reference from other threads no matter what the runtime condition is:
class SomeClass {
void calledByMultipleThreads(){
UnsafeStuff mystuff = new UnsafeStuff();
mystuff.modifySomeStuff();
System.out.println(mystuff.toString());
}
}
Here, the UnsafeStuff is allocated within the method and goes out of scope when the method returns.. In other words, the Java spec is ensuring statically that the object is always confined to one thread. So, it is not the runtime condition or the way you use it that is ensuring the confinement, but more the Java spec.
In fact, modern JVM sometimes allocate such objects on stack, unlike the first example (haven't personally checked this, but I don't think at least current JVMs do).
Yet in other words, in the fist example the JVM can't be sure if the object is confined within a thread by just looking inside of calledByMultipleThreads() (who knows what other methods are messing with SomeClass.map). In the latter example, it can.
Edit: But what if I still want to
share the object with another thread?
Let's say that after thread A finishes
with object O, thread B wants to
access O. In this case, can O still be
confined to B after A is done with it?
I don't think it is called "confined" in this case. When you do this, you are just ensuring that an object is not accessed concurrently. This is how EJB concurrency works. You still have to "safely publish" the shared object in question to the threads.
So when an object is confined to a thread, no other thread can have access to it?
That's what thread confinement means - the object can only EVER be accessed by one thread.
Is that what it means to be confined to a thread?
See above.
How does one keep an object confined to a thread?
The general principle is to not put the reference somewhere that would allow another thread to see it. It is a little bit complicated to enumerate a set of rules that will ensure this, but (for instance) if
you create a new object, and
you never assign the object's reference to an instance or class variable, and
you never call a method that does this for the reference,
then the object will be thread confined.
I guess that's what want to say. Like creating a object inside the run method and not passing the reference to any other instance.
Simple example:
public String s;
public void run() {
StringBuilder sb = new StringBuilder();
sb.append("Hello ").append("world");
s = sb.toString();
}
The StringBuilder instance is thread-safe because it is confined to the thread (that executes this run method)
One way is "stack confinement" in which the object is a local variable confined to the thread's stack, so no other thread can access it. In the method below, the list is a local variable and doesn't escape from the method. The list doesn't have to be threadsafe because it is confined to the executing thread's stack. No other thread can modify it.
public String foo(Item i, Item j){
List<Item> list = new ArrayList<Item>();
list.add(i);
list.add(j);
return list.toString();
}
Another way of confining an object to a thread is through the use of a ThreadLocal variable which allows each thread to have its own copy. In the example below, each thread will have its own DateFormat object and so you don't need to worry about the fact that DateFormat is not thread-safe because it won't be accessed by multiple threads.
private static final ThreadLocal<DateFormat> df
= new ThreadLocal<DateFormat>(){
#Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyyMMdd");
}
};
Further Reading
See: http://codeidol.com/java/java-concurrency/Sharing-Objects/Thread-Confinement/
A more formal means of maintaining
thread confinement is ThreadLocal,
which allows you to associate a
per-thread value with a value-holding
object. Thread-Local provides get and
set accessormethods that maintain a
separate copy of the value for each
thread that uses it, so a get returns
the most recent value passed to set
from the currently executing thread.
It holds a copy of object per one thread, thread A can't access copy of thread B and broke it's invariants if you will do it specially (for example, assign ThreadLocal value to static variable or expose it using other methods)
That's exactly what it means. The object itself is accessed by only one thread, and is thus thread-safe. ThreadLocal objects are a kind of objects that are bound to an only thread
I means that only code running in one thread accesses the object.
When this is the case, the object doesn't need to be "thread safe"
i have a variable on my "SharedPreferences", that is accesed by two different threads, one in a service, and one in a activity.
There is a easy way to protect this variable to be accesed by two threads at once?
i need to protect this code:
configEditor.putString("mylatitude", ""+currentLocation.getLatitude());
configEditor.putString("mylongitude", ""+currentLocation.getLongitude());
configEditor.commit();
i tryed with this but doesn't works:
Object LOCK = new Object();
synchronized (LOCK){
configEditor.putString("mylatitude", ""+currentLocation.getLatitude());
configEditor.putString("mylongitude", ""+currentLocation.getLongitude());
configEditor.commit();
}
thanks
Object LOCK = new Object();
synchronized (LOCK) {
// lines of Java code that has to be thread safe
}
EDIT: edit the code to be exactly for the situation when the code is modifying several variables and it has to be thread-safe. For a single variable (as is in the title of the question) lock the variable itself, you don't need a separate lock for it.
I'm not sure, but I believe using a Handler may be what you need.
Take a look at this article, which explains when and how to use them. It also provides some code samples which may be helpful.
Try something like this:
public class MyClass {
private final Object lock = new Object();
public myMethod() {
...
synchronized (lock) {
// At most one thread is executing this
// at the same time for this instance
}
...
}
}
The important thing is that the lock object should be an instance (and not local) variable, so that every thread uses the same lock for that particular instance of MyClass. Most of the time you want it to be final so that there is no posibility of changing it by mistake.
If you make the lock static, then at most one thread will be executing the synchronized section, no matter in which instance of MyClass.
EDIT:
For your particular case, you can adapt the following idea:
public class Service {
public void doSomethingWithConfigEditor() {
ConfigEditor configEditor = // get configEditor
synchronized (configEditor) {
// something with configEditor
}
}
}
public class Activity {
public void doAnotherThingWithConfigEditor() {
ConfigEditor configEditor = // get configEditor
synchronized (configEditor) {
// another thing with configEditor
}
}
}
By synchronizing on configEditor, you guarantee that those two blocks of code never execute in parallel on the same instance of ConfigEditor.
This is typically done using critical sections aka mutexes. Before accessing the variable, your thread should aquire a lock on the mutex. While the mutex is locked, any attempt to aquire another lock will wait until the previous lock is released. This way, threads will wait for each other when accessing the variable.
You need to put the synchronized block in both locations that access the variable which you are trying to protect. Protecting it only one of the locations doesn't help.
Are you sure this is in two different threads? Your service code will only be running in a different thread if you are executing due to someone calling through to your IBinder interface from another process (or another thread in your own process).