I am creating a Runnable in the following way:
public class AbcRunnable implements Runnable
{
Qwe qwe;
Rst rst;
public void run() {
// some operations on qwe and rst which are changing their value
}
}
public class AbcThreadPool {
private final AbcThreadPoolExecutor executor;
public InventoryAvailabilityThreadPool(final AbcRunnableFactory factory,
final Integer poolSize) {
executor = new AbcThreadPoolExecutor(factory, poolSize);
for (int i = 0; i < poolSize; ++i) {
executor.execute(factory.get());
}
}
private static class AbcThreadPoolExecutor extends ThreadPoolExecutor {
private final AbcRunnableFactory factory;
public AbcThreadPoolExecutor(final AbcRunnableFactory factory,
final int poolSize) {
super(poolSize, poolSize, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
this.factory = factory;
allowCoreThreadTimeOut(false);
}
}
}
public class AbcRunnableFactory {
#Override
public AbcRunnable get() {
return new AbcRunnable();
}
}
Initialization of Qwe and Rst is being done by the guice module, say, as follows:
#Provides
#Singleton
private AbcRunnableFactory provideAbcRunnableFactory() {
return new AbcRunnableFactory(
new Qwe(), new Rst());
}
So, here AbcRunnable has 2 variables: qwe and rst. My question here is, do different Runnables have their own variables or are they getting shared? Please help in explaining this.
I am very confused when trying to understand what is thread safe or not. So, this may be a very naive question.
Each new instance of AbcRunnable will have its own set of fields (list1 and map1). Since your loop is calling factory.get() in each iteration, and that creates a new AbcRunnable, each thread pool task will have a unique instance of the runnable and its contained fields.
Now, you haven't showed how you initialize the fields inside AbcRunnable:
If you create new List and Map instances in the constructor, then nothing is shared between threads and your code is thread-safe.
If you are passing in any of these values from the outside, then your different AbcRunnable instances could potentially share references to the same list/map and you will need to ensure synchronized access to the data (or use a concurrent collection implementation, which is already thread-safe).
The answer depends how you instantiate your runables. There is a lot going on here so let's simplify. Say we have a very large set of n numbers we want to sum. We can split the set in two and create 2 threads, when they return we just sum the two results. Because we could divide the set in two and sum at the end there is nothing shared, everything is thread safe.
Now let's say we want to know how many of our n numbers have been summed as they are working. We need a shared counter that each thread can increment as the two threads sum. So if the counter is 100 and both threads try to increment it at the same time, both threads will read 100 add 1 and return 101 to memory, the new count will be 101 but really 102 numbers have been summed. For shared variables like our counter we need to make sure only one thread at a time has access at a time if they are writing to it.
In your case if you send the same list or map to two threads you would have a problem because lists and maps are passed by reference or the address in memory is what is sent to the new thread so both might try to modify them at the same time. However, if you split your list and map into distinct values before sending it then you should be fine.
Related
Problem statement:- //This is a example, Actual array size is very large
suppose there is class A
public class A{
public static int aa[]=new int[5];
public computeaa(){
for(int i=0;i<5;i++)
aa[i] = useaa(i);
}
//this below function can compute aa[i] value
public int useaa(int i){
if(i<=0)
return 1;
if(aa[i]!=0)
return aa[i];
else
return useaa[i-1]+useaa[i-2];
}
}
And RecursiveAction class B
#Override
protected void compute() {
// TODO Auto-generated method stub
A z=new A();
A.computeaa();
}
public static void main(String[] args) {
List<B> tasks =new ArrayList<B>();
for(int i=1; i<=2; i++){
//There is 2 fork will created
B =new B();
tasks.add(B);
B.fork();
}
if (tasks.size() > 0) {
for (B task : tasks) {
task.join();
}
}
}
Doubt?
suppose fork 1 computes static variable aa[2], and suppose when fork 2 going to computes aa[2], can this fork 2 get the value aa[2] which was computed by fork1 or it will compute seperately??
By my understanding fork 2 in some cases easily access fork1's aa, suppose fork 2 wanted to compute aa[3],It can get the value which was already computed by fork 1. But the problem is suppose when fork 1 will try to compute aa[4], for calculating aa[4], it need aa[3], which fork 1 already computed but can it possible if fork 1 try to get aa[3], but by chance it get the access of aa[3] of fork 1 which was not calculate... again it creating a mess.
I am very puzzle by fork join kindly help
There is simple problem, i want to compute some array which is used by same class, but while creating more then one object i want to use the same array which was computed by other object so that my computation time reduced.
How can i copy or get that array to another object, so that this object doesn't need to compute?
suppose fork 1 computes static variable aa[2], and suppose when fork 2 going to computes aa[2], can this fork 2 get the value aa[2]
which was computed by fork1 or it will compute seperately?
Supposing that the two B tasks run in different threads -- over which you elect not to exercise any control -- those two threads are accessing the same element of the same array object without any synchronization. Either thread can read the value written by the other. Moreover, they may read a different value if they access that array element again. The program is not correctly synchronized and therefore there is no guarantee of sequential consistency.
By my understanding fork 2 in some cases easily access fork1's aa, suppose fork 2 wanted to compute aa[3],It can get the value which
was already computed by fork 1. But the problem is suppose when fork 1
will try to compute aa[4], for calculating aa[4], it need aa[3], which
fork 1 already computed but can it possible if fork 1 try to get
aa[3], but by chance it get the access of aa[3] of fork 1 which was
not calculate... again it creating a mess.
Yes, you judge rightly -- both about possible behaviors and about it being a mess.
There is simple problem, i want to compute some array which is used by
same class, but while creating more then one object i want to use the
same array which was computed by other object so that my computation
time reduced. How can i copy or get that array to another object, so
that this object doesn't need to compute?
Under some circumstances, you might have different threads compute disjoint sections of the array in parallel. The computation presented in the question is not amenable to that, however, because of the dependencies between the data. Because no element past index 1 can be computed before the previous 2 have been computed, computation of the elements needs to be serialized, one way or another. You cannot achieve that any faster than by devoting a single thread to the job.
After such a computation is completed, you can share the initialized array among threads, provided that they synchronize with the completion of the computation one way or another. Additional synchronization requirements apply if any of the threads modify the array after the initial computation is complete.
Your particular case is a bit tricky, because few actions with synchronization significance are present. In particular, your array elements are not (and cannot be) final, and you cannot be confident that the threads in which your tasks run are started only when you fork(); if you had the latter then everything the main thread did before would automatically synchronize with the work of the tasks. As it is, you might do something like this:
public class A {
// not static:
public int aa[] = new int[5];
public void computeAa() {
aa[0] = 1;
aa[1] = 1;
for (int i = 2; i < aa.length; i++) {
aa[i] = aa[i - 1] + aa[i - 2];
}
}
public int getAa(int i) {
return (i < 0) ? 1 : aa[i];
}
}
public class B extends RecursiveAction {
private A myA;
public RecursiveAction(A a) {
myA = a;
}
#Override
protected void compute() {
synchronized (myA) {
// ensure that myA's initialization is complete
while (myA.aa[0] == 0) {
// not yet initialized
myA.wait();
}
}
// ... do something with myA (without modifying it) ...
}
public static void main(String[] args) {
A theA = new A();
synchronized(theA) {
// synchronize the initialization of theA, because other threads will
// check it
theA.computeAa();
// wake up any threads waiting on the initialization
theA.notifyAll();
}
List<B> tasks = new ArrayList<B>();
for(int i = 1; i <= 2; i++){
//There is 2 fork will created
B = new B(theA);
tasks.add(B);
B.fork();
}
for (B task : tasks) {
task.join();
}
}
}
Note here that the main thread creates an instance of A and initializes it before forking any tasks. It provides that instance to each B (thus they share it).
TL;DR: in Java I have N threads, each using a shared collection. ConcurrentHashMap allows me to lock on write, but not on read. What I need is to lock a specific item of the collection, read the previous data, do some computation, and update the values. If two threads receive two messages from the same sender, the second thread has to wait for the first one to finish, before doing its stuff.
Long version:
These threads are receiving chronologically ordered messages, and they have to update the collection basing on a messageSenderID.
My code simplified is as follow:
public class Parent {
private Map<String, MyObject> myObjects;
ExecutorService executor;
List<Future<?>> runnables = new ArrayList<Future<?>>();
public Parent(){
myObjects= new ConcurrentHashMap<String, MyObject>();
executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
WorkerThread worker = new WorkerThread("worker_" + i);
Future<?> future = executor.submit(worker);
runnables.add(future);
}
}
private synchronized String getMessageFromSender(){
// Get a message from the common source
}
private synchronized MyObject getMyObject(String id){
MyObject myObject = myObjects.get(id);
if (myObject == null) {
myObject = new MyObject(id);
myObjects.put(id, myObject);
}
return myObject;
}
private class WorkerThread implements Runnable {
private String name;
public WorkerThread(String name) {
this.name = name;
}
#Override
public void run() {
while(!isStopped()) {
JSONObject message = getMessageFromSender();
String id = message.getString("id");
MyObject myObject = getMyObject(id);
synchronized (myObject) {
doLotOfStuff(myObject);
}
}
}
}
}
So basically I have one producer and N consumers, to speed-up processing, but the N consumers have to deal with a common base of data and chronological order has to be respected.
I am currently using a ConcurrentHashMap, but I'm willing to change it if needed.
The code seems to work if messages with same ID arrive enough apart (> 1 second), but if I get two messages with the same ID in the distance of microseconds, I get two threads dealing with the same item in the collection.
I GUESS that my desired behavior is:
Thread 1 Thread 2
--------------------------------------------------------------
read message 1
find ID
lock that ID in collection
do computation and update
read message 2
find ID
lock that ID in collection
do computation and update
While I THINK that this is what happens:
Thread 1 Thread 2
--------------------------------------------------------------
read message 1
read message 2
find ID
lock that ID in collection
do computation and update
find ID
lock that ID in collection
do computation and update
I thought about doing something like
JSONObject message = getMessageFromSender();
synchronized(message){
String id = message.getString("id");
MyObject myObject = getMyObject(id);
synchronized (myObject) {
doLotOfStuff(myObject);
} // well maybe this inner synchronized is superfluous, at this point
}
But I think that would kill the whole purpose of having a multithreaded structure, since I would read one message at a time, and the workers are not doing anything else; and it would be like if I was using a SynchronizedHashMap instead of a ConcurrentHashMap.
For the record, I report here the solution I implemented eventually. I'm not sure it is optimal and I still have to test for performances, but at least the input is handed properly.
public class Parent implements Runnable {
private final static int NUM_WORKERS = 10;
ExecutorService executor;
List<Future<?>> futures = new ArrayList<Future<?>>();
List<WorkerThread> workers = new ArrayList<WorkerThread>();
#Override
public void run() {
executor = Executors.newFixedThreadPool(NUM_WORKERS);
for (int i = 0; i < NUM_WORKERS; i++) {
WorkerThread worker = new WorkerThread("worker_" + i);
Future<?> future = executor.submit(worker);
futures.add(future);
workers.add(worker);
}
while(!isStopped()) {
byte[] message = getMessageFromSender();
byte[] id = getId(message);
int n = Integer.valueOf(Byte.toString(id[id.length-1])) % NUM_WORKERS;
if(n >= 0 && n <= (NUM_WORKERS-1)){
workers.get(n).addToQueue(line);
}
}
}
private class WorkerThread implements Runnable {
private String name;
private Map<String, MyObject> myObjects;
private LinkedBlockingQueue<byte[]> queue;
public WorkerThread(String name) {
this.name = name;
}
public void addToQueue(byte[] line) {
queue.add(line);
}
#Override
public void run() {
while(!isStopped()) {
byte[] message= queue.poll();
if(line != null) {
String id = getId(message);
MyObject myObject = getMyObject(id);
doLotOfStuff(myObject);
}
}
}
}
}
Conceptually this is kind of routing problem. What you need to is:
Get your your main thread (single thread) reading messages of the queue and push the data to a FIFO queue per id.
Get a single thread to consume messages from each queue.
Locking examples will (probably) not work as after the second message order is not guaranteed even if fair=true.
From Javadoc:
Even when this lock has been set to use a fair ordering policy, a call to tryLock() will immediately acquire the lock if it is available, whether or not other threads are currently waiting for the lock.
One thing for you to decide is if you want to create a a thread per queue (which will exit once the queue is empty) or keep the fixed size thread pool and manage get the extra bits to assign threads to queues.
So, you get a single thread reading from the original queue and writing to the per-id-queues and the you also get one thread per id reading from individual queues. This will ensure task serialization.
In terms of performance, you should see significant speed-up as long as the incoming messages have a nice distribution (id-wise). If you get mostly same-id messages then task will be serialized and also include the overhead for control object creation and synchronization.
You could use a separate Map for your locks. There's also a WeakHashMap that will automatically discard entries when the key is no longer present.
static final Map<String, Lock> locks = Collections.synchronizedMap(new WeakHashMap<>());
public void lock(String id) throws InterruptedException {
// Grab a Lock out of the map.
Lock l = locks.computeIfAbsent(id, k -> new ReentrantLock());
// Lock it.
l.lockInterruptibly();
}
public void unlock(String id) throws InterruptedException {
// Is it locked?
Lock l = locks.get(id);
if ( l != null ) {
l.unlock();
}
}
I think you have the right idea with your synchronized blocks, except you mis-analyze a bit and go too far in any case. The outer synchronized block shouldn't force you into dealing with only one message at a time, it just keeps multiple threads from accessing the same message at once. But you don't need it. You really only need that inner synchronized block, on the MyObject instance. That will ensure that only one thread at a time can access any given MyObject instance, while enabling other threads to access messages, the Map and other MyObject instances as much as they want.
JSONObject message = getMessageFromSender();
String id = message.getString("id");
MyObject myObject = getMyObject(id);
synchronized (myObject) {
doLotOfStuff(myObject);
}
If you don't like that, and the updates to the MyObject instances all involve single-method invocations, then you could just synchronize all of those methods. You still retain concurrency in the Map, but you're protecting the MyObject itself from concurrent updates.
class MyObject {
public synchronize void updateFoo() {
// ...
}
public synchronize void updateBar() {
// ...
}
}
When any Thread accesses any updateX() method it will automatically lock out any other Thread from accessing that or any other synchronized method. That would be simplest, if your updates match that pattern.
If not, then you'll need to make all of your worker Threads cooperate by using some sort of locking protocol. The ReentrantLock that OldCurmudgeon suggests is a good choice, but I would put it on MyObject itself. To keep things ordered properly, you should use the fairness parameter (see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/ReentrantLock.html#ReentrantLock-boolean-). "When set true, under contention, locks favor granting access to the longest-waiting thread."
class MyObject {
private final ReentrantLock lock = new ReentrantLock(true);
public void lock() {
lock.lock();
}
public void unlock() {
lock.unlock();
}
public void updateFoo() {
// ...
}
public void updateBar() {
// ...
}
}
Then you could update things like this:
JSONObject message = getMessageFromSender();
String id = message.getString("id");
MyObject myObject = getMyObject(id);
myObject.lock();
try {
doLotOfStuff(myObject);
}
finally {
myObject.unlock();
}
The important takeaway is that you don't need to control access to the messages, nor the Map. All you need to do is ensure that any given MyObject is being updated by at most one thread at a time.
Actually here is a design idea: when a consumer takes a request to work on your Object it should actually remove the object with that ID from your list of Objects and then re-insert it back once the processing is done. Then any other consumer getting request to work on the object with the same id should be in blocking mode waiting for the object with that ID to re-appear in your list. You will need to add a management to keep record of all existing objects so when you can distinguish between the object that exists already but is not currently in the list (i.e. being processed by some other consumer) and the object that does not exist yet.
You could get some speedup if you split up the JSON parsing from the doLotsOfStuff(). One thread listens for messages, parses them, then puts the parsed message on a Queue to maintain chronological order. A second thread reads from that Queue and doesLotsOfStuff with no need for locking.
However, since you apparently need more than a 2X speedup this is probably insufficient.
Added
Another possibility is multiple HashMaps. For example, if all the IDs are ints, make 10 HashMaps for IDs ending with 0,1,2... Incoming messages get directed to one of 10 threads, which parse the JSON and update their relevant Map. Order is maintained within each Map, and there are no locking or contention issues. Assuming the message IDs are randomly distributed this yields up to a 10x speedup, though there is one extra layer of overhead to get at your Map. e.g.
Thread JSON Threads 0-9
--------------------------------------------------------------
while (notInterrupted) {
read / parse next JSON message
mapToUse = ID % 10
pass JSON to that Thread's queue
}
while (notInterrupted) {
take JSON off queue
// I'm the only one with writing to Map#N
do computation and update ID
}
Is it bad programming to initialize two threads with the same instance of a runnable? What difference would it make to initialize with separate instances of a runnable, and does sharing memory locations at all for the same instance of a runnable have anything to do with performance?
public static void main(String[] args)throws Exception {
H h = new H();
H h2 = new H();
Thread j = new Thread(h);
j.setName("11");
Thread jj = new Thread(h);//instead of new H()
jj.setName("22");
j.start();
jj.start();
}
class H implements Runnable {
public void run() {
while(true) {
System.out.println(Thread.currentThread().getName());
}
}
}
It's absolutely fine to do it so long as the code you're running is designed to support that. Not only will it save some memory by having a single instance instead of multiple instances, but if those threads are trying to communicate via shared data, then it may be absolutely required!
Admittedly communicating via shared state is where threading often gets tricky, so this needs to be done carefully, but from the point of view of the threading system itself, there's absolutely no problem in having two threads call the run method of a single Runnable instance.
Since H doesn't have any instance state, using multiple instances won't matter. You need to take care when the Runnable instances start storing state.
public class Main implements Runnable {
volatile int i;
public void run() {
for (i = 0; i < 100; i++) {
System.out.println(i);
}
}
public static void main(String[] args) {
Main a = new Main();
Thread t1 = new Thread(a);
Thread t2 = new Thread(a);
t1.start();
t2.start();
}
}
What gets printed? When you do need to share state between threads, it's a good idea to use the classes in java.util.concurrent. They were written primarily by an expert in multithreading (Doug Lea, author of Concurrent Programming in Java) and tested by many people. Save yourself some heartache. :)
Is it bad programming to initialize two threads with the same instance of a runnable?
Not specifically. However, if the Runnable instance has instance fields, then you'll need to make sure that all access to the fields by the thread is properly synchronized, and this will make the code more complicated.
What difference would it make to initialize with separate instances of a runnable, and does sharing memory locations at all for the same instance of a runnable have anything to do with performance?
The memory saved by sharing a Runnable instance between multiple threads is insignificant ... unless the Runnable holds a significant amount of instance data. (And if it does, the chances are that this will make the instance non-shareable.)
Your H class is an example where sharing instances is safe, but pointless since the memory saving is insignificant. (A Runnable object with no instance fields occupies roughly 8 to 16 bytes, depending on the platform.)
To make understand easily(based on the comment of Stephen), added the below program block about the impact of accessing the instance variable from a non-synchronized block with the same instance of Runnable displays the unexpected results.
public class SynchronizedInstanceMethod implements Runnable{
private int counter;
public SynchronizedInstanceMethod(int counterValue){
this.counter = counterValue;
}
private synchronized void displayMessage(){
System.out.println(" Display Message ");
}
private void modifyCounter(){
this.counter++;
System.out.println("Value -- "+ this.counter);
}
#Override
public void run() {
this.displayMessage();
this.modifyCounter();
}
public static void main(String[] args) {
SynchronizedInstanceMethod instance = new SynchronizedInstanceMethod(5);
new Thread(instance).start();
new Thread(instance).start();
}
}
I'm looking for a way to synchronize a method based on the parameter it receives, something like this:
public synchronized void doSomething(name){
//some code
}
I want the method doSomething to be synchronized based on the name parameter like this:
Thread 1: doSomething("a");
Thread 2: doSomething("b");
Thread 3: doSomething("c");
Thread 4: doSomething("a");
Thread 1 , Thread 2 and Thread 3 will execute the code without being synchronized , but Thread 4 will wait until Thread 1 has finished the code because it has the same "a" value.
Thanks
UPDATE
Based on Tudor explanation I think I'm facing another problem:
here is a sample of the new code:
private HashMap locks=new HashMap();
public void doSomething(String name){
locks.put(name,new Object());
synchronized(locks.get(name)) {
// ...
}
locks.remove(name);
}
The reason why I don't populate the locks map is because name can have any value.
Based on the sample above , the problem can appear when adding / deleting values from the hashmap by multiple threads in the same time, since HashMap is not thread-safe.
So my question is if I make the HashMap a ConcurrentHashMap which is thread safe, will the synchronized block stop other threads from accessing locks.get(name) ??
TL;DR:
I use ConcurrentReferenceHashMap from the Spring Framework. Please check the code below.
Although this thread is old, it is still interesting. Therefore, I would like to share my approach with Spring Framework.
What we are trying to implement is called named mutex/lock. As suggested by Tudor's answer, the idea is to have a Map to store the lock name and the lock object. The code will look like below (I copy it from his answer):
Map<String, Object> locks = new HashMap<String, Object>();
locks.put("a", new Object());
locks.put("b", new Object());
However, this approach has 2 drawbacks:
The OP already pointed out the first one: how to synchronize the access to the locks hash map?
How to remove some locks which are not necessary anymore? Otherwise, the locks hash map will keep growing.
The first problem can be solved by using ConcurrentHashMap. For the second problem, we have 2 options: manually check and remove locks from the map, or somehow let the garbage collector knows which locks are no longer used and the GC will remove them. I will go with the second way.
When we use HashMap, or ConcurrentHashMap, it creates strong references. To implement the solution discussed above, weak references should be used instead (to understand what is a strong/weak reference, please refer to this article or this post).
So, I use ConcurrentReferenceHashMap from the Spring Framework. As described in the documentation:
A ConcurrentHashMap that uses soft or weak references for both keys
and values.
This class can be used as an alternative to
Collections.synchronizedMap(new WeakHashMap<K, Reference<V>>()) in
order to support better performance when accessed concurrently. This
implementation follows the same design constraints as
ConcurrentHashMap with the exception that null values and null keys
are supported.
Here is my code. The MutexFactory manages all the locks with <K> is the type of the key.
#Component
public class MutexFactory<K> {
private ConcurrentReferenceHashMap<K, Object> map;
public MutexFactory() {
this.map = new ConcurrentReferenceHashMap<>();
}
public Object getMutex(K key) {
return this.map.compute(key, (k, v) -> v == null ? new Object() : v);
}
}
Usage:
#Autowired
private MutexFactory<String> mutexFactory;
public void doSomething(String name){
synchronized(mutexFactory.getMutex(name)) {
// ...
}
}
Unit test (this test uses the awaitility library for some methods, e.g. await(), atMost(), until()):
public class MutexFactoryTests {
private final int THREAD_COUNT = 16;
#Test
public void singleKeyTest() {
MutexFactory<String> mutexFactory = new MutexFactory<>();
String id = UUID.randomUUID().toString();
final int[] count = {0};
IntStream.range(0, THREAD_COUNT)
.parallel()
.forEach(i -> {
synchronized (mutexFactory.getMutex(id)) {
count[0]++;
}
});
await().atMost(5, TimeUnit.SECONDS)
.until(() -> count[0] == THREAD_COUNT);
Assert.assertEquals(count[0], THREAD_COUNT);
}
}
Use a map to associate strings with lock objects:
Map<String, Object> locks = new HashMap<String, Object>();
locks.put("a", new Object());
locks.put("b", new Object());
// etc.
then:
public void doSomething(String name){
synchronized(locks.get(name)) {
// ...
}
}
The answer of Tudor is fine, but it's static and not scalable. My solution is dynamic and scalable, but it goes with increased complexity in the implementation. The outside world can use this class just like using a Lock, as this class implements the interface. You get an instance of a parameterized lock by the factory method getCanonicalParameterLock.
package lock;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public final class ParameterLock implements Lock {
/** Holds a WeakKeyLockPair for each parameter. The mapping may be deleted upon garbage collection
* if the canonical key is not strongly referenced anymore (by the threads using the Lock). */
private static final Map<Object, WeakKeyLockPair> locks = new WeakHashMap<>();
private final Object key;
private final Lock lock;
private ParameterLock (Object key, Lock lock) {
this.key = key;
this.lock = lock;
}
private static final class WeakKeyLockPair {
/** The weakly-referenced parameter. If it were strongly referenced, the entries of
* the lock Map would never be garbage collected, causing a memory leak. */
private final Reference<Object> param;
/** The actual lock object on which threads will synchronize. */
private final Lock lock;
private WeakKeyLockPair (Object param, Lock lock) {
this.param = new WeakReference<>(param);
this.lock = lock;
}
}
public static Lock getCanonicalParameterLock (Object param) {
Object canonical = null;
Lock lock = null;
synchronized (locks) {
WeakKeyLockPair pair = locks.get(param);
if (pair != null) {
canonical = pair.param.get(); // could return null!
}
if (canonical == null) { // no such entry or the reference was cleared in the meantime
canonical = param; // the first thread (the current thread) delivers the new canonical key
pair = new WeakKeyLockPair(canonical, new ReentrantLock());
locks.put(canonical, pair);
}
}
// the canonical key is strongly referenced now...
lock = locks.get(canonical).lock; // ...so this is guaranteed not to return null
// ... but the key must be kept strongly referenced after this method returns,
// so wrap it in the Lock implementation, which a thread of course needs
// to be able to synchronize. This enforces a thread to have a strong reference
// to the key, while it isn't aware of it (as this method declares to return a
// Lock rather than a ParameterLock).
return new ParameterLock(canonical, lock);
}
#Override
public void lock() {
lock.lock();
}
#Override
public void lockInterruptibly() throws InterruptedException {
lock.lockInterruptibly();
}
#Override
public boolean tryLock() {
return lock.tryLock();
}
#Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return lock.tryLock(time, unit);
}
#Override
public void unlock() {
lock.unlock();
}
#Override
public Condition newCondition() {
return lock.newCondition();
}
}
Of course you'd need a canonical key for a given parameter, otherwise threads would not be synchronized as they would be using a different Lock. Canonicalization is the equivalent of the internalization of Strings in Tudor's solution. Where String.intern() is itself thread-safe, my 'canonical pool' is not, so I need extra synchronization on the WeakHashMap.
This solution works for any type of Object. However, make sure to implement equals and hashCode correctly in custom classes, because if not, threading issues will arise as multiple threads could be using different Lock objects to synchronize on!
The choice for a WeakHashMap is explained by the ease of memory management it brings. How else could one know that no thread is using a particular Lock anymore? And if this could be known, how could you safely delete the entry out of the Map? You would need to synchronize upon deletion, because you have a race condition between an arriving thread wanting to use the Lock, and the action of deleting the Lock from the Map. All these things are just solved by using weak references, so the VM does the work for you, and this simplifies the implementation a lot. If you inspected the API of WeakReference, you would find that relying on weak references is thread-safe.
Now inspect this test program (you need to run it from inside the ParameterLock class, due to private visibility of some fields):
public static void main(String[] args) {
Runnable run1 = new Runnable() {
#Override
public void run() {
sync(new Integer(5));
System.gc();
}
};
Runnable run2 = new Runnable() {
#Override
public void run() {
sync(new Integer(5));
System.gc();
}
};
Thread t1 = new Thread(run1);
Thread t2 = new Thread(run2);
t1.start();
t2.start();
try {
t1.join();
t2.join();
while (locks.size() != 0) {
System.gc();
System.out.println(locks);
}
System.out.println("FINISHED!");
} catch (InterruptedException ex) {
// those threads won't be interrupted
}
}
private static void sync (Object param) {
Lock lock = ParameterLock.getCanonicalParameterLock(param);
lock.lock();
try {
System.out.println("Thread="+Thread.currentThread().getName()+", lock=" + ((ParameterLock) lock).lock);
// do some work while having the lock
} finally {
lock.unlock();
}
}
Chances are very high that you would see that both threads are using the same lock object, and so they are synchronized. Example output:
Thread=Thread-0, lock=java.util.concurrent.locks.ReentrantLock#8965fb[Locked by thread Thread-0]
Thread=Thread-1, lock=java.util.concurrent.locks.ReentrantLock#8965fb[Locked by thread Thread-1]
FINISHED!
However, with some chance it might be that the 2 threads do not overlap in execution, and therefore it is not required that they use the same lock. You could easily enforce this behavior in debugging mode by setting breakpoints at the right locations, forcing the first or second thread to stop wherever necessary. You will also notice that after the Garbage Collection on the main thread, the WeakHashMap will be cleared, which is of course correct, as the main thread waited for both worker threads to finish their job by calling Thread.join() before calling the garbage collector. This indeed means that no strong reference to the (Parameter)Lock can exist anymore inside a worker thread, so the reference can be cleared from the weak hashmap. If another thread now wants to synchronize on the same parameter, a new Lock will be created in the synchronized part in getCanonicalParameterLock.
Now repeat the test with any pair that has the same canonical representation (= they are equal, so a.equals(b)), and see that it still works:
sync("a");
sync(new String("a"))
sync(new Boolean(true));
sync(new Boolean(true));
etc.
Basically, this class offers you the following functionality:
Parameterized synchronization
Encapsulated memory management
The ability to work with any type of object (under the condition that equals and hashCode is implemented properly)
Implements the Lock interface
This Lock implementation has been tested by modifying an ArrayList concurrently with 10 threads iterating 1000 times, doing this: adding 2 items, then deleting the last found list entry by iterating the full list. A lock is requested per iteration, so in total 10*1000 locks will be requested. No ConcurrentModificationException was thrown, and after all worker threads have finished the total amount of items was 10*1000. On every single modification, a lock was requested by calling ParameterLock.getCanonicalParameterLock(new String("a")), so a new parameter object is used to test the correctness of the canonicalization.
Please note that you shouldn't be using String literals and primitive types for parameters. As String literals are automatically interned, they always have a strong reference, and so if the first thread arrives with a String literal for its parameter then the lock pool will never be freed from the entry, which is a memory leak. The same story goes for autoboxing primitives: e.g. Integer has a caching mechanism that will reuse existing Integer objects during the process of autoboxing, also causing a strong reference to exist. Addressing this, however, this is a different story.
Check out this framework. Seems you're looking for something like this.
public class WeatherServiceProxy {
...
private final KeyLockManager lockManager = KeyLockManagers.newManager();
public void updateWeatherData(String cityName, Date samplingTime, float temperature) {
lockManager.executeLocked(cityName, new LockCallback() {
public void doInLock() {
delegate.updateWeatherData(cityName, samplingTime, temperature);
}
});
}
https://code.google.com/p/jkeylockmanager/
I've created a tokenProvider based on the IdMutexProvider of McDowell.
The manager uses a WeakHashMap which takes care of cleaning up unused locks.
You could find my implementation here.
I've found a proper answer through another stackoverflow question: How to acquire a lock by a key
I copied the answer here:
Guava has something like this being released in 13.0; you can get it out of HEAD if you like.
Striped more or less allocates a specific number of locks, and then assigns strings to locks based on their hash code. The API looks more or less like
Striped<Lock> locks = Striped.lock(stripes);
Lock l = locks.get(string);
l.lock();
try {
// do stuff
} finally {
l.unlock();
}
More or less, the controllable number of stripes lets you trade concurrency against memory usage, because allocating a full lock for each string key can get expensive; essentially, you only get lock contention when you get hash collisions, which are (predictably) rare.
Just extending on to Triet Doan's answer, we also need to take care of if the MutexFactory can be used at multiple places, as with currently suggested code we will end up with same MutexFactory at all places of its usage.
For example:-
#Autowired
MutexFactory<CustomObject1> mutexFactory1;
#Autowired
MutexFactory<CustomObject2> mutexFactory2;
Both mutexFactory1 & mutexFactory2 will refer to the same instance of factory even if their type differs, this is due to the fact that a single instance of MutexFactory is created by spring during application startup and same is used for both mutexFactory1 & mutexFactory2.
So here is the extra Scope annotation that needs to be put in to avoid above case-
#Component
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class MutexFactory<K> {
private ConcurrentReferenceHashMap<K, Object> map;
public MutexFactory() {
this.map = new ConcurrentReferenceHashMap<>();
}
public Object getMutex(K key) {
return this.map.compute(key, (k, v) -> v == null ? new Object() : v);
}
}
I've used a cache to store lock objects. The my cache will expire objects after a period, which really only needs to be longer that the time it takes the synchronized process to run
`
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
...
private final Cache<String, Object> mediapackageLockCache = CacheBuilder.newBuilder().expireAfterWrite(DEFAULT_CACHE_EXPIRE, TimeUnit.SECONDS).build();
...
public void doSomething(foo) {
Object lock = mediapackageLockCache.getIfPresent(foo.toSting());
if (lock == null) {
lock = new Object();
mediapackageLockCache.put(foo.toString(), lock);
}
synchronized(lock) {
// execute code on foo
...
}
}
`
I have a much simpler, scalable implementation akin to #timmons post taking advantage of guavas LoadingCache with weakValues. You will want to read the help files on "equality" to understand the suggestion I have made.
Define the following weakValued cache.
private final LoadingCache<String,String> syncStrings = CacheBuilder.newBuilder().weakValues().build(new CacheLoader<String, String>() {
public String load(String x) throws ExecutionException {
return new String(x);
}
});
public void doSomething(String x) {
x = syncStrings.get(x);
synchronized(x) {
..... // whatever it is you want to do
}
}
Now! As a result of the JVM, we do not have to worry that the cache is growing too large, it only holds the cached strings as long as necessary and the garbage manager/guava does the heavy lifting.
I have a method which takes a list and do some processing on it and it updates another global list. I need to run multiple instances of this method with different lists input in parallel.
Does multi-threading support this? If yes, how can i use it i.e.: what shall i put in the thread? Examples are highly appreciated.
I am thinking of having a static list in the thread class which gets updated by the different instances of the thread while running (the list contains strings and counters, so the update is adding new strings or increasing the counters of existing ones).. i need to read whatever gets added to this global list every 10 seconds and print it.. is using static list suitable for this and how can i make it thread safe?
Yes, that's a very common usage of multithreaded programming.
class ListProcessor implements Runnable {
/* field/s representing param/s */
public ListProcessor(/* param/s */) {
/* ... */
}
#Override
public void run() {
/* process list */
}
}
Then, when you want to actually process some lists.
class SomeClass {
ExecutorService listProcessor;
public SomeClass(/* ... */) {
listProcessor = ExecutorService.newFixedThreadPool(numThreads);
/* for each thread, however you want to do it */
listProcessor.execute(new ListProcessor(/* param/s */));
/* when finished adding threads */
listProcessor.shutdown();
/* note that the above two lines of code (execute/shutdown) can be
* placed anywhere in the code. I just put them in the constructor to
* facilitate this example.
*/
}
}
#purtip31 has a start for the parallel processing stuff.
I'm concerned about the results - you mention that you update a "global list". If multiple threads at a time are trying to update that list at the same time there could be problems. A couple of options:
Make sure that list is properly thread safe. This may or may not be easy - depends on exactly what is getting changed.
Use ExecutorService, but with the invokeAll() method, which runs a bunch of Callables in parallel and waits till they are all done. Then you can go through all of the results and update them one at a time. No threading issues with the results. This means that your code will have to implement Callable instead of Runnable (not a big deal). I have a blog with an example here
Well Sam...i m not much cleared with your question.....
try this out....
Following is a code which would help u to run mulitple instances.......
Main thread
public class mainprocess
{
public static LinkedList globallist;
public static String str;
public int num;
public static void main(String Data[])
{
globallist = new LinkedList();
// LinkedList will be passed as pass by reference.....
// globalist is made static and assigned likewise for global use..
childprocess.assignlist(globallist);
childprocess p1 = new childprocess("string input"); // a string input...
childprocess p2 = new childprocess(number input); // a number input...
p1.t.join();
p2.t.join();
}
}
The Child Thread.....
public class childprocess implements Runnable
{
public Thread t1,t2;
public boolean inttype,stringtype;
String string;
int num;
public static LinkedList temp = new Linkedlist();
public static assignlist(LinkedList ll)
{
temp = ll;
}
public childprocess(String str)
{
string = str;
t1 = new Thread(this,"stringThread");
t1.start();
}
#override
public childprocess(int n)
{
num = n;
t2 = new Thread(this,"numberThread");
t2.start();
}
#override
public void run()
{
// Both will be executed in a threader manner based on the condition...
if(Thread.currentThread().getName().equals("stringThread")
{
// your process using string......
childprocess.temp.add(str);
}
else if(Thread.currentThread().getName().equals("numberThread")
{
// your process using number.....
chilprocess.temp.add(num);
}
}
}
If you are using functions that should be restricted to only one thread at a time...
include the syntax....
public synchronized func_type func_name()
{
}