I was reading about semaphore's and in the code example it confused me why a semaphore was used when the code uses sychronization around the method that is ultimately called. Isn't that doing the same thing, i.e. restricting 1 thread at a time to perform the mutation?
class Pool {
private static final int MAX_AVAILABLE = 100;
private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
public Object getItem() throws InterruptedException {
available.acquire();
return getNextAvailableItem();
}
public void putItem(Object x) {
if (markAsUnused(x))
available.release();
}
// Not a particularly efficient data structure; just for demo
protected Object[] items = ... whatever kinds of items being managed
protected boolean[] used = new boolean[MAX_AVAILABLE];
protected synchronized Object getNextAvailableItem() {
for (int i = 0; i < MAX_AVAILABLE; ++i) {
if (!used[i]) {
used[i] = true;
return items[i];
}
}
return null; // not reached
}
protected synchronized boolean markAsUnused(Object item) {
for (int i = 0; i < MAX_AVAILABLE; ++i) {
if (item == items[i]) {
if (used[i]) {
used[i] = false;
return true;
} else
return false;
}
}
return false;
}
}
I'm referring to the call to getItem() which calls acquire(), and then calls getNextAvailableItem, but that is synchronized anyhow.
What am I missing?
Reference: http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Semaphore.html
The semaphore and the synchronized block are doing two different jobs.
The synchronized keyword is protecting getNextAvailableItem() when it is accessing and mutating the array of items. An operation that would corrupt if it was not restricted to one thread at a time.
The semaphore will allow up to 100 threads through, significantly more than 1. Its purpose in this code sample is to block requests for an object from the pool when the pool is empty, and to then unblock one thread when an object is returned to the pool. Without the semaphore, things would look like they were working until the pool was empty. At that time requesting threads would not block and wait for an object to be returned, but would instead receive null.
A Semaphore gives you a thread-safe counter that blocks when the acquire has been called beyond the initial limit. release can be used to undo an acquire.
It will guarantee that if a call to acquire succeeds there is sufficient capacity to hold the new item.
In the sample there are loops that look for a free item. Using a Semaphore ensures that none of those loops are begun until there is a free item.
synchronized only guarantees that ony one thread can execute this section of code at a time.
Related
I'm running with five threads, and I have a list of objects (which I initialize independently of the threads).
The objects in the list use a boolean as a flag, so I know if they have been handled by another Thread already. Also, my Thread has an Integer for its "ID" (so U know which thread is currently working).
The problem: The first thread that gets a hand on the for-loop will handle all objects in the list, but I want the threads to alternate. What am I doing wrong?
the run() method looks similar to this:
void run() {
for (int i = 0; i < list.size(); i++) {
ListObject currentObject = list.get(i);
synchronized (currentObject) {
if (currentObject.getHandled == false) {
currentObject.setHandled(true);
System.out.println("Object is handled by " + this.getID());
} else {
continue;
}
}
}
}
TL;DR Explicitly or implicitly divide the list among the threads; and synchronization if really needed;
The problem: The first thread that gets a hand on the for-loop will
handle all objects in the list, but i want the threads to alternate.
What am I doing wrong?
That is expectable this entire block of code
for (int i = 0; i < list.size(); i++) {
ListObject currentObject = list.get(i);
synchronized (currentObject) {
....
}
}
is basically being executed sequentially since each thread synchronizes in every iteration using the Object currentObject implicit lock. All five threads enter the run method, however one of them enters first in the synchronized (currentObject) all the other will wait in turn for the first thread to release the currentObject implicitly lock. When the thread is finished moves on to the next iteration while the remaining threads are still in the previous iteration. Hence, the first thread entering synchronized (currentObject) will have a head start, and will be steps head of the previous threads, and will likely compute all the remains iterations. Consequently:
The first thread that gets a hand on the for-loop will handle all
objects in the list,
As it is you would be better off performance-wise and readability-wise executing the code sequentially.
Assumption
I am assuming that
the objects stored on the list are not being accessed elsewhere at the same time that those threads are iterating through the list;
the list does not contain multiple references to the same object;
I would suggest that instead of every thread iterating over the entire list and synchronizing in every iteration -- which is extremely non perform and actually defeats the point of parallelism -- every thread would compute a different chunk of the list (e.g., dividing the iterations of the for loop among the threads). For instance:
Approach 1: Using Parallel Stream
If you don't have to explicitly parallelize your code then consider using ParallelStream:
list.parallelStream().forEach(this::setHandled);
private void setHandled(ListObject currentObject) {
if (!currentObject.getHandled) {
currentObject.setHandled(true);
System.out.println("Object is handled by " + this.getID());
}
}
Approach 2 : If you have to explicitly parallelized the code using executors
I'm running five threads,
(as first illustrated by ernest_k)
ExecutorService ex = Executors.newFixedThreadPool(5);
for (ListObject l : list)
ex.submit(() -> setHandled(l));
...
private void setHandled(ListObject currentObject) {
if (!currentObject.getHandled) {
currentObject.setHandled(true);
System.out.println("Object is handled by " + this.getID());
}
}
Approach 3: If you have to explicitly use the Threads
void run() {
for (int i = threadID; i < list.size(); i += total_threads) {
ListObject currentObject = list.get(i);
if (currentObject.getHandled == false) {
currentObject.setHandled(true);
System.out.println("Object is handled by " + this.getID());
}
}
}
In this approach, I am splitting the iterations of the for loop among threads in a round-robin fashion, assuming that total_threads is the number of threads that will compute the run method, and that each thread will have a unique threadID ranging from 0 to total_threads - 1. Other approaches to distribute the iterations among threads would also so be visible, for instance dynamically distribution the iterations among threads:
void run() {
for (int i = task.getAndIncrement(); i < list.size(); i = task.getAndIncrement();) {
ListObject currentObject = list.get(i);
if (currentObject.getHandled == false) {
currentObject.setHandled(true);
System.out.println("Object is handled by " + this.getID());
}
}
}
where task would be an atomic integer (i.e., AtomicInteger task = new AtomicInteger();).
In all approaches the idea is the same assign different chunks of the list to the threads so that those threads can execute those chunks independently of each other.
If the assumptions 1. and 2. cannot be made then you can still apply the aforementioned logic of splitting the iterations among threads but you will need to add synchronization, in my examples to the follow block of code:
private void setHandled(ListObject currentObject) {
if (!currentObject.getHandled) {
currentObject.setHandled(true);
System.out.println("Object is handled by " + this.getID());
}
}
as it is you can just turn the currentObject field into an AtomicBoolean as follows:
private void setHandled(ListObject currentObject) {
if (currentObject.getHandled.compareAndSet(false, true)) {
System.out.println("Object is handled by " + this.getID());
}
}
otherwise use the synchronized clause:
private void setHandled(ListObject currentObject) {
synchronized (currentObject) {
if (!currentObject.getHandled) {
currentObject.setHandled(true);
System.out.println("Object is handled by " + this.getID());
}
}
}
I'm trying to write game of life on many threads, 1 cell = 1 thread, it requires synchronization between threads, so no thread will start calculating it new state before other thread does not finish reading previous state. here is my code
public class Cell extends Processor{
private static int count = 0;
private static Semaphore waitForAll = new Semaphore(0);
private static Semaphore waiter = new Semaphore(0);
private IntField isDead;
public Cell(int n)
{
super(n);
count ++;
}
public void initialize()
{
this.algorithmName = Cell.class.getSimpleName();
isDead = new IntField(0);
this.addField(isDead, "state");
}
public synchronized void step()
{
int size = neighbours.size();
IntField[] states = new IntField[size];
int readElementValue = 0;
IntField readElement;
sendAll(new IntField(isDead.getDist()));
Cell.waitForAll.release();
//here wait untill all other threads finish reading
while (Cell.waitForAll.availablePermits() != Cell.count) {
}
//here release semaphore neader lower
Cell.waiter.release();
for (int i = 0; i < neighbours.size(); i++) {
readElement = (IntField) reciveMessage(neighbours.get(i));
states[i] = (IntField) reciveMessage(neighbours.get(i));
}
int alive = 0;
int dead = 0;
for(IntField ii: states)
{
if(ii.getDist() == 1)
alive++;
else
dead++;
}
if(isDead.getDist() == 0)
{
if(alive == 3)
isDead.setValue(1);
else
;
}
else
{
if(alive == 3 || alive == 2)
;
else
isDead.setValue(0);
}
try {
while(Cell.waiter.availablePermits() != Cell.count)
{
;
//if every thread finished reading we can acquire this semaphore
}
Cell.waitForAll.acquire();
while(Cell.waitForAll.availablePermits() != 0)
;
//here we make sure every thread ends step in same moment
Cell.waiter.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
processor
class extends thread and in run method if i turn switch on it calls step() method. well it works nice for small amount of cells but when i run abou 36 cells it start to be very slow, how can repair my synchronization so it woudl be faster?
Using large numbers of threads tends not to be very efficient, but 36 is not so many that I would expect that in itself to produce a difference that you would characterize as "very slow". I think more likely the problem is inherent in your strategy. In particular, I suspect this busy-wait is problematic:
Cell.waitForAll.release();
//here wait untill all other threads finish reading
while (Cell.waitForAll.availablePermits() != Cell.count) {
}
Busy-waiting is always a performance problem because you are tying up the CPU with testing the condition over and over again. This busy-wait is worse than most, because it involves testing the state of a synchronization object, and this not only has extra overhead, but also introduces extra interference among threads.
Instead of busy-waiting, you want to use one of the various methods for making threads suspend execution until a condition is satisfied. It looks like what you've actually done is created a poor-man's version of a CyclicBarrier, so you might consider instead using CyclicBarrier itself. Alternatively, since this is a learning exercise you might benefit from learning how to use Object.wait(), Object.notify(), and Object.notifyAll() -- Java's built-in condition variable implementation.
If you insist on using semaphores, then I think you could do it without the busy-wait. The key to using semaphores is that it is being able to acquire the semaphore (at all) that indicates that the thread can proceed, not the number of available permits. If you maintain a separate variable with which to track how many threads are waiting on a given semaphore at a given point, then each thread reaching that point can determine whether to release all the other threads (and proceed itself) or whether to block by attempting to acquire the semaphore.
I have the following piece of code
Boolean flag = new Boolean(false);
flag = true;
Will the second line (assignment) cause a recreation of the initial object (basically a call to new()) in the JVM? I am asking because I am using a Boolean object to synchronize multiple threads, and I am afraid that if a re-initialization takes places, the waiting threads will not see the change in value.
In my application, there are multiple threads that are given a reference to the previous Boolean object. Only one thread changes the objects value to true, and the rest wait until the object's value becomes true. So, if T1 is the thread that changes the value, its code is like:
synchronized(flag) {
flag = true;
flag.notifyAll();
}
and the rest of the threads (T2) will have code like:
synchronized(flag) {
while(flag == false)
wait();
if(flag == true) {
//do something
}
}
Therefore, the question is that after the assignment of true to flag, will the other threads (T2) still have access to the original object?
Thanks,
Nick
The assignment flag = false is a boxing conversion. It will get compiled as flag=Boolean.valueOf(false) which will end up returning the constant Boolean.FALSE.
So the answer is, it will not create a new object but it will change the variable flag as it assigns an instance distinct from your previous result of new Boolean(false).
It’s not quite clear what you are actually doing but in general, synchronizing on a mutable variable is broken design.
The problem is that you are mixing the value that makes up your condition and the object to synchronize on. The simplest implementation of your updated intention is to use a simple boolean flag and synchronize on the instance that contains the flag:
class WithFlag {
private boolean flag;
public synchronized void setToTrue() {
if(!flag) {
flag=true;
notifyAll();
}
}
public synchronized void waitForTrue() throws InterruptedException {
while(!flag) wait();
}
}
Note that declaring an instance method synchronized is similar to wrap its code with synchronized(this) { … }
If you want to use a boolean to synchronize threads, you should consider using AtomicBoolean, which is specifically designed for this purpose.
The other answers have already explained that when you say flag=false, it is a boxing conversion which will return the constant Boolean.FALSE. One important point that the other answers have covered but not emphasized on is that when you obtain a lock on two Boolean objects that were assigned the same value through a boxing conversion, it is as good as obtaining a lock on one Boolean object.
My answer attempts to give an example to explain this. Consider the following code that creates two threads that obtain a lock on a Boolean.
public class BooleanTest {
public static void main(String[] args) {
BooleanTest test = new BooleanTest();
test.booleanTest();
}
private void booleanTest() {
BooleanLockTester booleanLock1 = new BooleanLockTester();
booleanLock1.setBooleanLock(true);
BooleanLockTester booleanLock2 = new BooleanLockTester();
booleanLock2.setBooleanLock(true);
BooleanLocker booleanLocker1 = new BooleanLocker(booleanLock1);
BooleanLocker booleanLocker2 = new BooleanLocker(booleanLock2);
Thread threadOne = new Thread(booleanLocker1);
Thread threadTwo = new Thread(booleanLocker2);
threadOne.start();
threadTwo.start();
}
private class BooleanLocker implements Runnable {
private BooleanLockTester booleanLockObj;
public BooleanLocker(BooleanLockTester booleanLockObj) {
this.booleanLockObj = booleanLockObj;
}
#Override
public void run() {
booleanLockObj.testLockOnBoolean();
}
}
private class BooleanLockTester {
private Boolean booleanLock = false;
public synchronized void testLockOnBoolean() {
synchronized (booleanLock) {
for (int i = 0; i<1000000000; ++i) {
System.out.println(Thread.currentThread().getName());
}
}
}
public void setBooleanLock(Boolean booleanLock) {
this.booleanLock = booleanLock;
}
}
}
In the above example, the two threads will never be able to enter the for loop together. When you run the program, you will see that the thread that starts first will start printing on the console and only when it is finished, the next thread will start printing to the console.
Let's make a small change in the above code :
Change the following line in the code :
booleanLock2.setBooleanLock(true);
To this :
booleanLock2.setBooleanLock(false);
You will now see that the threads stop behaving and print to the console in a random order. This is because the threads now obtain a lock on two different objects.
I'm Learning Java multithreading and I have problem, I can't understand Semaphores. How can I execute threads in this order? for example : on image1 : the 5-th thread start running only then 1-st and 2-nd is finished to execute.
Image 2:
Image 1:
I upload now images for better understanding . :))
Usually in java you use mutexes (also called monitors), which prohibits that two or more threads access the code region proctected by that mutex
That code region is defined using the sychronized statement
sychronized(mutex) {
// mutual exclusive code begin
// ...
// ...
// mutual exclusive code end
}
where mutex is defined as e.g:
Object mutex = new Object();
To prevent a task from beeing started you need advanced technics, such as barriers, defined in java.util.concurrency package.
But first make yourself confortable with the synchronized statement.
If you think that you will often use multi threading in java, you might want to read
"Java Concurrency in Practise"
Synchronized is used so that each thread will enter that method or that portion of the code on at a time. If you want to
public class CountingSemaphore {
private int value = 0;
private int waitCount = 0;
private int notifyCount = 0;
public CountingSemaphore(int initial) {
if (initial > 0) {
value = initial;
}
}
public synchronized void waitForNotify() {
if (value <= waitCount) {
waitCount++;
try {
do {
wait();
} while (notifyCount == 0);
} catch (InterruptedException e) {
notify();
} finally {
waitCount--;
}
notifyCount--;
}
value--;
}
public synchronized void notifyToWakeup() {
value++;
if (waitCount > notifyCount) {
notifyCount++;
notify();
}
}
}
This is an implementation of a counting semaphore. It maintains counter variables ‘value’, ‘waitCount’ and ‘notifyCount’. This makes the thread to wait if value is lesser than waitCount and notifyCount is empty.
You can use Java Counting Semaphore. Conceptually, a semaphore maintains a set of permits. Each acquire() blocks if necessary until a permit is available, and then takes it. Each release() adds a permit, potentially releasing a blocking acquirer. However, no actual permit objects are used; the Semaphore just keeps a count of the number available and acts accordingly.
Semaphores are often used to restrict the number of threads than can access some (physical or logical) resource. For example, here is a class that uses a semaphore to control access to a pool of items:
class Pool {
private static final MAX_AVAILABLE = 100;
private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
public Object getItem() throws InterruptedException {
available.acquire();
return getNextAvailableItem();
}
public void putItem(Object x) {
if (markAsUnused(x))
available.release();
}
// Not a particularly efficient data structure; just for demo
protected Object[] items = ... whatever kinds of items being managed
protected boolean[] used = new boolean[MAX_AVAILABLE];
protected synchronized Object getNextAvailableItem() {
for (int i = 0; i < MAX_AVAILABLE; ++i) {
if (!used[i]) {
used[i] = true;
return items[i];
}
}
return null; // not reached
}
protected synchronized boolean markAsUnused(Object item) {
for (int i = 0; i < MAX_AVAILABLE; ++i) {
if (item == items[i]) {
if (used[i]) {
used[i] = false;
return true;
} else
return false;
}
}
return false;
}
}
Before obtaining an item each thread must acquire a permit from the semaphore, guaranteeing that an item is available for use. When the thread has finished with the item it is returned back to the pool and a permit is returned to the semaphore, allowing another thread to acquire that item. Note that no synchronization lock is held when acquire() is called as that would prevent an item from being returned to the pool. The semaphore encapsulates the synchronization needed to restrict access to the pool, separately from any synchronization needed to maintain the consistency of the pool itself.
A semaphore initialized to one, and which is used such that it only has at most one permit available, can serve as a mutual exclusion lock. This is more commonly known as a binary semaphore, because it only has two states: one permit available, or zero permits available. When used in this way, the binary semaphore has the property (unlike many Lock implementations), that the "lock" can be released by a thread other than the owner (as semaphores have no notion of ownership). This can be useful in some specialized contexts, such as deadlock recovery.
Say I have an AtomicReferenceto a list of objects:
AtomicReference<List<?>> batch = new AtomicReference<List<Object>>(new ArrayList<Object>());
Thread A adds elements to this list: batch.get().add(o);
Later, thread B takes the list and, for example, stores it in a DB: insertBatch(batch.get());
Do I have to do additional synchronization when writing (Thread A) and reading (Thread B) to ensure thread B sees the list the way A left it, or is this taken care of by the AtomicReference?
In other words: if I have an AtomicReference to a mutable object, and one thread changes that object, do other threads see this change immediately?
Edit:
Maybe some example code is in order:
public void process(Reader in) throws IOException {
List<Future<AtomicReference<List<Object>>>> tasks = new ArrayList<Future<AtomicReference<List<Object>>>>();
ExecutorService exec = Executors.newFixedThreadPool(4);
for (int i = 0; i < 4; ++i) {
tasks.add(exec.submit(new Callable<AtomicReference<List<Object>>>() {
#Override public AtomicReference<List<Object>> call() throws IOException {
final AtomicReference<List<Object>> batch = new AtomicReference<List<Object>>(new ArrayList<Object>(batchSize));
Processor.this.parser.parse(in, new Parser.Handler() {
#Override public void onNewObject(Object event) {
batch.get().add(event);
if (batch.get().size() >= batchSize) {
dao.insertBatch(batch.getAndSet(new ArrayList<Object>(batchSize)));
}
}
});
return batch;
}
}));
}
List<Object> remainingBatches = new ArrayList<Object>();
for (Future<AtomicReference<List<Object>>> task : tasks) {
try {
AtomicReference<List<Object>> remainingBatch = task.get();
remainingBatches.addAll(remainingBatch.get());
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof IOException) {
throw (IOException)cause;
}
throw (RuntimeException)cause;
}
}
// these haven't been flushed yet by the worker threads
if (!remainingBatches.isEmpty()) {
dao.insertBatch(remainingBatches);
}
}
What happens here is that I create four worker threads to parse some text (this is the Reader in parameter to the process() method). Each worker saves the lines it has parsed in a batch, and flushes the batch when it is full (dao.insertBatch(batch.getAndSet(new ArrayList<Object>(batchSize)));).
Since the number of lines in the text isn't a multiple of the batch size, the last objects end up in a batch that isn't flushed, since it's not full. These remaining batches are therefore inserted by the main thread.
I use AtomicReference.getAndSet() to replace the full batch with an empty one. It this program correct with regards to threading?
Um... it doesn't really work like this. AtomicReference guarantees that the reference itself is visible across threads i.e. if you assign it a different reference than the original one the update will be visible. It makes no guarantees about the actual contents of the object that reference is pointing to.
Therefore, read/write operations on the list contents require separate synchronization.
Edit: So, judging from your updated code and the comment you posted, setting the local reference to volatile is sufficient to ensure visibility.
I think that, forgetting all the code here, you exact question is this:
Do I have to do additional synchronization when writing (Thread A) and
reading (Thread B) to ensure thread B sees the list the way A left it,
or is this taken care of by the AtomicReference?
So, the exact response to that is: YES, atomic take care of visibility. And it is not my opinion but the JDK documentation one:
The memory effects for accesses and updates of atomics generally follow the rules for volatiles, as stated in The Java Language Specification, Third Edition (17.4 Memory Model).
I hope this helps.
Adding to Tudor's answer: You will have to make the ArrayList itself threadsafe or - depending on your requirements - even larger code blocks.
If you can get away with a threadsafe ArrayList you can "decorate" it like this:
batch = java.util.Collections.synchronizedList(new ArrayList<Object>());
But keep in mind: Even "simple" constructs like this are not threadsafe with this:
Object o = batch.get(batch.size()-1);
The AtomicReference will only help you with the reference to the list, it will not do anything to the list itself. More particularly, in your scenario, you will almost certainly run into problems when the system is under load where the consumer has taken the list while the producer is adding an item to it.
This sound to me like you should be using a BlockingQueue. You can then Limit the memory footprint if you producer is faster than your consumer and let the queue handle all contention.
Something like:
ArrayBlockingQueue<Object> queue = new ArrayBlockingQueue<Object> (50);
// ... Producer
queue.put(o);
// ... Consumer
List<Object> queueContents = new ArrayList<Object> ();
// Grab everything waiting in the queue in one chunk. Should never be more than 50 items.
queue.drainTo(queueContents);
Added
Thanks to #Tudor for pointing out the architecture you are using. ... I have to admit it is rather strange. You don't really need AtomicReference at all as far as I can see. Each thread owns its own ArrayList until it is passed on to dao at which point it is replaced so there is no contention at all anywhere.
I am a little concerned about you creating four parser on a single Reader. I hope you have some way of ensuring each parser does not affect the others.
I personally would use some form of producer-consumer pattern as I have described in the code above. Something like this perhaps.
static final int PROCESSES = 4;
static final int batchSize = 10;
public void process(Reader in) throws IOException, InterruptedException {
final List<Future<Void>> tasks = new ArrayList<Future<Void>>();
ExecutorService exec = Executors.newFixedThreadPool(PROCESSES);
// Queue of objects.
final ArrayBlockingQueue<Object> queue = new ArrayBlockingQueue<Object> (batchSize * 2);
// The final object to post.
final Object FINISHED = new Object();
// Start the producers.
for (int i = 0; i < PROCESSES; i++) {
tasks.add(exec.submit(new Callable<Void>() {
#Override
public Void call() throws IOException {
Processor.this.parser.parse(in, new Parser.Handler() {
#Override
public void onNewObject(Object event) {
queue.add(event);
}
});
// Post a finished down the queue.
queue.add(FINISHED);
return null;
}
}));
}
// Start the consumer.
tasks.add(exec.submit(new Callable<Void>() {
#Override
public Void call() throws IOException {
List<Object> batch = new ArrayList<Object>(batchSize);
int finishedCount = 0;
// Until all threads finished.
while ( finishedCount < PROCESSES ) {
Object o = queue.take();
if ( o != FINISHED ) {
// Batch them up.
batch.add(o);
if ( batch.size() >= batchSize ) {
dao.insertBatch(batch);
// If insertBatch takes a copy we could merely clear it.
batch = new ArrayList<Object>(batchSize);
}
} else {
// Count the finishes.
finishedCount += 1;
}
}
// Finished! Post any incopmplete batch.
if ( batch.size() > 0 ) {
dao.insertBatch(batch);
}
return null;
}
}));
// Wait for everything to finish.
exec.shutdown();
// Wait until all is done.
boolean finished = false;
do {
try {
// Wait up to 1 second for termination.
finished = exec.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
}
} while (!finished);
}