I want to create a class which will be accessed by multiple threads for getting a data. So I have a method like this:
public static String getData(){
//some logic before returning the value
// return data once initialized
}
Now there will be method which will set that data:
private void setData(){
}
I want this setData to be called only once, so thought of including it in static block:
static {
setData()
}
Now I have these questions:
I'm planning to create a static class for this, so that other threads can call like this:
ThreadSafe.getData();
In my getData, I want to check first the validity of that data before returning, if the data is invalid, I need to again call setData and then return it. Given this fact, I need to make getData synchronized right?
will my above approach work in a multi threading environment?
You can use synchronization:
public class ThreadSafe {
private static final Object monitor = new Object();
private static final String data;
static {
setData();
}
private static void setData() {
data = String.valueOf(System.currentTimeMillis());
}
public static String getData() {
synchronized(monitor) {
if (data.indexOf("7") < 0) {
// recalculate invalid data
setData();
}
return data;
}
}
}
You can achieve it in multiple ways.
You can use volatile variable ( If one Thread write/modify data and all other Threads read the data
You can use AtomicReference variables ( If multiple threads can read/modify shared data)
If you have some atomic transaction on top of these variables instead of just write & read data, you have to protect your business transaction code block with synchronized or other alternatives like Lock API.
Refer to this jenkov tutorial for more details.
Related SE posts with code examples:
Difference between volatile and synchronized in Java
Avoid synchronized(this) in Java?
When to use AtomicReference in Java?
What is the difference between atomic / volatile / synchronized?
I would say you better synchronise (with double lock checking) block that calls setData() in getData(). Assuming it's a rare case this should work faster on high load.
Related
Concurrent collection:
ConcurrentMap<LocalDate, A> ex = new ConcurrentHashMap<>();
class A {
AtomicLong C;
AtomicLong D
}
How can I synchronize by locking "C" and "D"? That is, I need to change "C" and "B" at the same time with a guarantee that while I change the other one, the first one does not change from external actions.
Thank you.
What you're solving for
You are describing that you want to:
allow a caller to modify something on an object
prevent any other callers (other threads) from modifying things at the same time
Solution description
This solution uses synchronized, though there are number of other mechanisms available in Java that would support this (several of which are covered in
the Lock Objects section of the Java Tutorials).
The way "synchronized" works is that you designate some code using the "synchronized" keyword, along with an object to synchronize on.
When your code runs, the JVM will guarantee that, for all code which is synchronized – on the same object – only one thread
can proceed at a time.
You can make a synchronized code block, like below. Note: this defines an Object named "lock", but it's just a name chosen for clarity when
reading the code – you could name it anything you like.
Object lock;
synchronized (lock) {
... // all things here run only when "lock" is available
}
You can also designate an entire method as being synchronized, like this:
public void synchronized print() {
System.out.println("hello");
}
This second example behaves like the first - it also locks on an object – but it's not clear at a glance what the object is; that is, how does
the JVM know which object to sychronize on? This approach works if the method itself is called on an object instance, and in that case the lock becomes this. I'll show an example below.
There's good info in the Java Tutorials about synchronized methods.
Solution #1: synchronized block using Object lock
Here are a few notes about a class AllowOneEditAtATime:
it has two private members: one and two
because they're private, they cannot be changed directly – so it would not be allowed to do something like this:
AllowOneEditAtATime a = new AllowOneEditAtATime();
a.one = new AtomicLong(1); // cannot change "one" directly because it is private
defines private Object lock – this is meant to act as the thing that two different synchronized code blocks will lock on. It's totally fine to have different blocks of code each synchronize on the same object. This is the main technique you're after.
uses a synchronized block inside setOne(), synchronizing on "lock"
uses another synchronized block inside the other method – setTwo() – also synchronizing on "lock"
because both setOne() and setTwo() are synchronized on the same object, one of them will be allowed to run at a time
class AllowOneEditAtATime1 {
private Object lock;
private AtomicLong one;
private AtomicLong two;
public void setOne(AtomicLong newOne) {
synchronized (lock) {
one = newOne;
}
}
public void setTwo(AtomicLong newTwo) {
synchronized (lock) {
two = newTwo;
}
}
}
Solution #2: synchronized block, using this
Solution #1 works fine, but it isn't necessary (in this case) to create an entire object just for locking. Instead, you can rely on the fact that
this code runs only after someone called new AllowOneEditAtATime(), which means there's always an object instance, which means inside the code
you can use this. The this keyword refers to the object instance itself, the actual instance of AllowOneEditAtATime.
So here's a variation using this (no more Object lock):
class AllowOneEditAtATime2 {
private AtomicLong one;
private AtomicLong two;
public void setOne(AtomicLong newOne) {
synchronized (this) {
one = newOne;
}
}
public void setTwo(AtomicLong newTwo) {
synchronized (this) {
two = newTwo;
}
}
}
Solution #3: synchronized methods, implicit lock
Solution #2 works fine, but since we're using this as the lock, and since the code paths fit with doing this, we can use
synchronized methods
instead of synchronized code blocks.
That means we can replace this:
public void setTwo(AtomicLong newTwo) {
synchronized (this) {
two = newTwo;
}
}
with this:
public synchronized void setOne(AtomicLong newOne) {
one = newOne;
}
Under the covers, the entire setOne() method is synchronized on this automatically, so it isn't necessary to
include synchronized (this) { .. }
at all. In Solution #2, both methods were doing that, so both can be replaced.
By synchronizing both methods, they will both be synchronized on the object instance (this), which is similar to Solution #2, but with less code.
class AllowOneEditAtATime3 {
private AtomicLong one;
private AtomicLong two;
public synchronized void setOne(AtomicLong newOne) {
one = newOne;
}
public synchronized void setTwo(AtomicLong newTwo) {
two = newTwo;
}
}
Any of the above would work, as would other synchronization mechanisms. As with all things, there are multiple ways you could solve the problem.
For additional reading,
the Concurrency lesson (in Java Tutorials) has good info
and might be worth your time.
I have a class with the following class level variables:
private LinkedBlockingQueue<Integer> inputQueue;
private StringBuffer textBuffer;
private int currentIndex;
private String[] p;
private List<String[]> pageList;
private int cursor;
The class has a method setInput() that could be accessed by multiple threads. The method changes all the above variables like this
public void setInput(String s) {
p[cursor] = input;
cursor++;
if (cursor == 1000) {
// UI logic
textBuffer.setLength(0);
p = new String[];
cursor = 0;
}
// Some other logic here
pageList.add(p);
currentIndex++;
if (!inputQueue.offer(currentIndex)) {
throw new RuntimeException();
}
}
These variables can be read by other code snippet in the class, but they are only modified in setInput(). And all the other methods in the class do not have thread safety issue. In other words, they are ensured to be called by the main thread. In this scenario, if I put synchronized keyword before method setInput(), then do I need to use the LinkedBlockingQueue from java.util.concurrent? Are those variables guaranteed to be thread safe when the method is synchronized? Thanks.
To be thread safe, all methods accessing the fields (reading and writing) should be synchronized
No, in your scenario making the setInput method synchronized is not enough. All methods accessing the variables need to be synchronized, also the methods which only read the variables, otherwise the variables might be read while setInput is executing and thus you might see an inconsistent state of the object.
If a lot of threads are reading the variables but only a few are writing them, making the reading methods also synchronized might be an unnecessary performance bottleneck. In that case it is better to use a ReadWriteLock, so that all reading threads may access the object at the same time.
We have an application that has a class which holds members that are populated via the database. Here is a representative example of the situation.
private AtomicBoolean data1Initialized = new AtomicBoolean(false);
protected SomeSynchronizedDataStructure<Object> data1 = <initializeit>;
protected final synchronized void initData1() {
if (data1Initialized.compareAndSet(false, true)){
// Populate data1 data structure from database
}
}
public SomeSynchronizedDataStructure<Object> getData1(){
initData1();
return data1;
}
And we have this same pattern for data1, data2, data3... dataN. Each dataStructure is not related to the other, they just are in the same class. This data is accessed across multiple threads. A few questions about this pattern:
Synchronizing the methods will make it so that threads have to wait for a boolean check across all different dataNs, correct? Which is unnecessary?
Does the data structure need to be synchronized? The data will not change throughout the life of the application. I would think that only initalizing it would need to be synchronized and access could happen unsynchronized.
Most important to me personally
Could this ever cause a deadlock? I think no, but I'm not experienced with threads.
As you are initialising at class creation time all you need is:
public class DataHolder {
// Note: 'final' is needed to ensure value is committed to memory before DataHolder
private final SomeSynchronizedDataStructure<Object> data1 = <initializeit>;
public SomeSynchronizedDataStructure<Object> getData1(){
return data1;
}
}
Because the "initializeit" code will be run in the class' constructor you know it will be ready by the time you have a class handle available to pass around anyway. E.g.:
DataHolder dataHolder = new DataHolder();
// dataHolder has already created the data structure by the time I do...
dataHolder.getData1();
If you did want to go with lazy loading you could simply use synchronized:
public class DataHolder {
private SomeSynchronizedDataStructure<Object> data1;
public synchronized SomeSynchronizedDataStructure<Object> getData1() {
// synchronized guarantees each thread will see "data1" just as the
// last thread left it.
if(data1 == null) {
data1 = initializeit();
}
return data1;
}
}
Synchronizing the methods will make it so that threads have to wait for a boolean check across all different dataNs, correct?
Correct.
Which is unnecessary?
Yes, it is unnecessary because the dataNs are unrelated.
Does the data structure need to be synchronized? The data will not change throughout the life of the application. I would think that only initalizing it would need to be synchronized and access could happen unsynchronized.
Again, correct. BarrySW19's answer gives you the pattern for safely initializing it without synchronizing.
Most important to me personally
Could this ever cause a deadlock? I think no, but I'm not experienced with threads.
It can't cause a deadlock in and of itself. However, if one of the data init methods invokes something else that is synchronized on another monitor (call it m), and meanwhile some other thread owns m and now tries to init one of the dataNs, that's deadlock.
public class Test {
private final Map<URI, Set<TestObject>> uriToTestObject = new HashMap<URI, Set<TestObject>>();
private final Map<Channel, TestObject> connToTestObject = new HashMap<Channel, TestObject>();
private static class TestObject {
private URI server;
private Channel channel;
private final long startNano = System.nanoTime();
private AtomicInteger count = new AtomicInteger(0);
}
}
This is a class which I am planning to use as a connection manager. There are two maps one will have server uri to connection details i.e Test object and other will have channel to TestObject i.e connection entry details, when connection is created then put channel testobject and server uri as per required in both the maps , when give another request first check in the map for that server uri and obtain a channel, similarly when channel is close remove from both the maps, its corresponding entries i.e channel object and test object, should I use concurrent hash map or should I use HashMap and then synchronize on the add remove methods, also I shall be using count AtomicInteger variable for statistics purpose it will be incremented and decremented.
My question here is in the multithreaded environment do I need to make my methods synchronized even if I use ConcurrentHashmap, as I would be doing some operations on both maps in one method.
Yes, you need synchronization in multi-threaded environment.
Its better if you go with block level synchronization instead of method level synchronization.
Code snippet:
Object lock = new Object();
void method1(){
synchronized(lock){
//do your operation on hash map
}
}
void method2(){
synchronized(lock){
//do your operation on hash map
}
}
And about ConcurrentHashMap
Retrieval operations (including get) generally do not block, so may
overlap with update operations (including put and remove).
So yes you still may need to syncronization even you used ConcurrentHashMap.
Since you need operate two Maps at the same time,
Make the method synchronized is better choice.
And HashMap is enough if method is synchronized
For a travel booking web application, where there are 100 concurrent users logged in,
should ticket booking and generating an "E-Ticket Number" be implemented by a "synchronized" or a "static synchronized" method?
Well, are you aware of the difference between a static method and an instance method in general?
The only difference that synchronized makes is that before the VM starts running that method, it has to acquire a monitor. For an instance method, the lock acquired is the one associated with the object you're calling the method on. For a static method, the lock acquired is associated with the type itself - so no other threads will be able to call any other synchronized static methods at the same time.
In other words, this:
class Test
{
static synchronized void Foo() { ... }
synchronized void Bar() { ... }
}
is roughly equivalent to:
class Test
{
static void Foo()
{
synchronized(Test.class)
{
...
}
}
void Bar()
{
synchronized(this)
{
...
}
}
}
Generally I tend not to use synchronized methods at all - I prefer to explicitly synchronize on a private lock reference:
private final Object lock = new Object();
...
void Bar()
{
synchronized(lock)
{
...
}
}
You haven't provided nearly enough information to determine whether your method should be a static or instance method, or whether it should be synchronized at all. Multithreading is a complex issue - I strongly suggest that you read up on it (through books, tutorials etc).
Jon's answer covers the difference hinted at in your question title.
However, I would say that neither should be used for generating a ticket number. On the assumption that these are being stored in a database, somewhere - the database should be responsible for generating the number when you insert the new record (presumably by an autoincrementing primary key, or something similar).
Failing that, if you must generate the number within Java code, I suspect that the synchronisation overhead might be quite noticeable with 100 concurrent users. If you are running on Java 1.5 or later, I'd use a java.util.concurrent.AtomicInteger to get the ticket number, which you can simply call as
private static final AtomicInteger ticketSequence;
static
{
final int greatestTicket = getHighestExistingTicketNumber(); // May not be needed if you can start from zero each time
ticketSequence = new AtomicInteger(greatestTicket + 1);
}
public /*static*/ int getNextTicketNumber()
{
return ticketSequence.incrementAndGet();
}
This gives you the concurrent global uniqueness you need in a much more efficient fashion than synchronizing every time you need an integer.