Good Day
I have a question relating ReentrantReadWriteLocks. I am trying to solve a problem where multiple reader threads should be able to operate in parallel on a data structure, while one writer thread can only operate alone (while no reader thread is active). I am implementing this with the ReentrantReadWriteLocks in Java, however from time measurement it seems that the reader threads are locking each other out aswell. I don't think this is supposed to happen, so I am wondering if I implemented it wrong. The way I implemented it is as follows:
readingMethod(){
lock.readLock().lock();
do reading ...
lock.readLock().unlock();
}
writingMethod(){
lock.writeLock().lock();
do writing ...
lock.writeLock().unlock();
}
Where the reading method is called by many different threads. From measuring the time, the reading method is being executed sequentially, even if the writing method is never invoked! Any Idea on what is going wrong here? Thank you in advance -Cheers
EDIT: I tried to come up with a SSCCE, I hope this is clear:
public class Bank {
private Int[] accounts;
public ReadWriteLock lock = new ReentrantReadWriteLock();
// Multiple Threads are doing transactions.
public void transfer(int from, int to, int amount){
lock.readLock().lock(); // Locking read.
// Consider this the do-reading.
synchronized(accounts[from]){
accounts[from] -= amount;
}
synchronized(accounts[to]){
accounts[to] += amount;
}
lock.readLock().unlock(); // Unlocking read.
}
// Only one thread does summation.
public int totalMoney(){
lock.writeLock().lock; // Locking write.
// Consider this the do-writing.
int sum = 0;
for(int i = 0; i < accounts.length; i++){
synchronized(accounts[i]){
sum += accounts[i];
}
}
lock.writeLock().unlock; // Unlocking write.
return sum;
}}
I know the parts inside the read-Lock are not actually reads but writes. I did it this way because there are multiple threads performing writes, while only one thread performs reads, but while reading, no changes can be made to the array. This works in my understanding. And again, the code inside the read-Locks works fine with multiple threads, as long as no write method and no read-locks are added.
Your code is so horribly broken that you should not worry about any performance implication. Your code is not thread safe. Never synchronize on a mutable variable!
synchronized(accounts[from]){
accounts[from] -= amount;
}
This code does the following:
read the contents of the array accounts at position from without any synchronization, thus possibly reading a hopelessly outdated value, or a value just being written by a thread still inside its synchronized block
lock on whatever object it has read (keep in mind that the identity of Integer objects created by auto-boxing is unspecified [except for the -128 to +127 range])
read again the contents of the array accounts at position from
subtract amount from its int value, auto-box the result (yielding a different object in most cases)
store the new object in array accounts at position from
This implies that different threads can write to the same array position concurrently while having a lock on different Integer instances found on their first (unsynchronized) read, opening the possibility of data races.
It also implies that threads may block each other on different array positions if these positions happen to have the same value happened to be represented by the same instance. E.g. pre-initializing the array with zero values (or all to the same value within the range -128 to +127) is a good recipe for getting close to single thread performance as zero (or these other small values) is one of the few Integer values being guaranteed to be represented by the same instance. Since you didn’t experience NullPointerExceptions, you obviously have pre-initialized the array with something.
To summarize, synchronized works on object instances, not variables. That’s why it won’t compile when trying to do it on int variables. Since synchronizing on different objects is like not having any synchronization at all, you should never synchronize on mutable variables.
If you want thread-safe, concurrent access to the different accounts, you may use AtomicIntegers. Such a solution will use exactly one AtomicInteger instance per account which will never change. Only its balance value will be updated using its thread-safe methods.
public class Bank {
private final AtomicInteger[] accounts;
public final ReadWriteLock lock = new ReentrantReadWriteLock();
Bank(int numAccounts) {
// initialize, keep in mind that this array MUST NOT change
accounts=new AtomicInteger[numAccounts];
for(int i=0; i<numAccounts; i++) accounts[i]=new AtomicInteger();
}
// Multiple Threads are doing transactions.
public void transfer(int from, int to, int amount){
final Lock sharedLock = lock.readLock();
sharedLock.lock();
try {
accounts[from].addAndGet(-amount);
accounts[to ].addAndGet(+amount);
}
finally {
sharedLock.unlock();
}
}
// Only one thread does summation.
public int totalMoney(){
int sum = 0;
final Lock exclusiveLock = lock.writeLock();
exclusiveLock.lock();
try {
for(AtomicInteger account: accounts)
sum += account.get();
}
finally {
exclusiveLock.unlock();
}
return sum;
}
}
For completeness, as I guess this question will arise, here is how a withdraw process forbidding taking more money than available may look like:
static void safeWithdraw(AtomicInteger account, int amount) {
for(;;) {
int current=account.get();
if(amount>current) throw new IllegalStateException();
if(account.compareAndSet(current, current-amount)) return;
}
}
It may be included by replacing the line accounts[from].addAndGet(-amount); by safeWithdraw(accounts[from], amount);.
Well after writing the example above, I remembered that there is the class AtomicIntegerArray which fits even better to this kind of task…
private final AtomicIntegerArray accounts;
public final ReadWriteLock lock = new ReentrantReadWriteLock();
Bank(int numAccounts) {
accounts=new AtomicIntegerArray(numAccounts);
}
// Multiple Threads are doing transactions.
public void transfer(int from, int to, int amount){
final Lock sharedLock = lock.readLock();
sharedLock.lock();
try {
accounts.addAndGet(from, -amount);
accounts.addAndGet(to, +amount);
}
finally {
sharedLock.unlock();
}
}
// Only one thread does summation.
public int totalMoney(){
int sum = 0;
final Lock exclusiveLock = lock.writeLock();
exclusiveLock.lock();
try {
for(int ix=0, num=accounts.length(); ix<num; ix++)
sum += accounts.get(ix);
}
finally {
exclusiveLock.unlock();
}
return sum;
}
You can run 2 threads on this test
static ReadWriteLock l = new ReentrantReadWriteLock();
static void readMehod() {
l.readLock().lock();
System.out.println(Thread.currentThread() + " entered");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
l.readLock().unlock();
System.out.println(Thread.currentThread() + " exited");
}
and see if both threads enter the readlock.
Related
So my problem essentially is,that even though I use static volatile int variable for incrementation some of my data doesn't remain unique which would be my goal(I number my elements).
public class Producer implements Runnable{
private String str;
private Fifo f;
private int i;
private static volatile int n=0;
public Producer(String str,int i,Fifo f) ....
public void run() {
try {
this.go();
} catch (InterruptedException e) {
;
}
}
void go() throws InterruptedException {
while(true) {
Thread.sleep(i);
int l=n++;
String k=str+" "+l+" ";
f.put(k);
System.out.println("produced "+str+" "+l+" "+System.currentTimeMillis()%100000);
}
}
}
My problem is in the function go(). I number my elements, I have multiple Producer objects running as independent threads, but sometimes they act like they have no clue whether n has been updated or not so I get same indexes.
Any ideas?
(I get what could be the problem, but I have no clue how to solve it.)
There seems to be a misunderstanding as to what volatile does. The keyword volatile introduces happens-before semantics between writes and reads. It does not, however, make multiple operations atomic.
If we were to write the semantics of n++ "by hand" (please never do this, it is for explanatory purposes only), it would look something like that:
final int result;
n = (result = n) + 1;
Ideone demo
Looking at this code, we see that we have to:
read the value of n,
store it in some temporary variable result,
increment it by 1, and
write the (incremented) value back to n
So we have multiple operations. If those operations are executed in parallel multiple times by different threads, then we can see a manifold of possible interweavings that lead to inconsistent data. For example, two threads could both read the (current) value of n. Both would increment the value by one and both would write the new value back to n. This means that two threads have executed the "increment", but the value of n has only incremented by 1 instead of 2.
We can use specialized classes - in this case AtomicInteger - to avoid this problem. The usage looks something like this:
public class Producer implements Runnable {
...
private static final AtomicInteger n = new AtomicInteger(0);
...
void go() throws InterruptedException {
while(true) {
...
int l = n.getAndIncrement();
...
}
}
}
I am referencing from Baeldung.com. Unfortunately, the article does not explain why this is not a thread safe code. Article
My goal is to understand how to create a thread safe method with the synchronized keyword.
My actual result is: The count value is 1.
package NotSoThreadSafe;
public class CounterNotSoThreadSafe {
private int count = 0;
public int getCount() { return count; }
// synchronized specifies that the method can only be accessed by 1 thread at a time.
public synchronized void increment() throws InterruptedException { int temp = count; wait(100); count = temp + 1; }
}
My expected result is: The count value should be 10 because of:
I created 10 threads in a pool.
I executed Counter.increment() 10 times.
I make sure I only test after the CountDownLatch reached 0.
Therefore, it should be 10. However, if you release the lock of synchronized using Object.wait(100), the method become not thread safe.
package NotSoThreadSafe;
import org.junit.jupiter.api.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static org.junit.jupiter.api.Assertions.assertEquals;
class CounterNotSoThreadSafeTest {
#Test
void incrementConcurrency() throws InterruptedException {
int numberOfThreads = 10;
ExecutorService service = Executors.newFixedThreadPool(numberOfThreads);
CountDownLatch latch = new CountDownLatch(numberOfThreads);
CounterNotSoThreadSafe counter = new CounterNotSoThreadSafe();
for (int i = 0; i < numberOfThreads; i++) {
service.execute(() -> {
try { counter.increment(); } catch (InterruptedException e) { e.printStackTrace(); }
latch.countDown();
});
}
latch.await();
assertEquals(numberOfThreads, counter.getCount());
}
}
This code has both of the classical concurrency problems: a race condition (a semantic problem) and a data race (a memory model related problem).
Object.wait() releases the object's monitor and another thread can enter into the synchronized block/method while the current one is waiting. Obviously, author's intention was to make the method atomic, but Object.wait() breaks the atomicity. As result, if we call .increment() from, let's say, 10 threads simultaneously and each thread calls the method 100_000 times, we get count < 10 * 100_000 almost always, and this isn't what we'd like to. This is a race condition, a logical/semantic problem. We can rephrase the code... Since we release the monitor (this equals to the exit from the synchronized block), the code works as follows (like two separated synchronized parts):
public void increment() {
int temp = incrementPart1();
incrementPart2(temp);
}
private synchronized int incrementPart1() {
int temp = count;
return temp;
}
private synchronized void incrementPart2(int temp) {
count = temp + 1;
}
and, therefore, our increment increments the counter not atomically. Now, let's assume that 1st thread calls incrementPart1, then 2nd one calls incrementPart1, then 2nd one calls incrementPart2, and finally 1st one calls incrementPart2. We did 2 calls of the increment(), but the result is 1, not 2.
Another problem is a data race. There is the Java Memory Model (JMM) described in the Java Language Specification (JLS). JMM introduces a Happens-before (HB) order between actions like volatile memory write/read, Object monitor's operations etc. https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4.5 HB gives us guaranties that a value written by one thread will be visible by another one. Rules how to get these guaranties are also known as Safe Publication rules. The most common/useful ones are:
Publish the value/reference via a volatile field (https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4.5), or as the consequence of this rule, via the AtomicX classes
Publish the value/reference through a properly locked field (https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4.5)
Use the static initializer to do the initializing stores
(http://docs.oracle.com/javase/specs/jls/se11/html/jls-12.html#jls-12.4)
Initialize the value/reference into a final field, which leads to the freeze action (https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.5).
So, to have the counter correctly (as JMM has defined) visible, we must make it volatile
private volatile int count = 0;
or do the read over the same object monitor's synchronization
public synchronized int getCount() { return count; }
I'd say that in practice, on Intel processors, you read the correct value without any of these additional efforts, with just simple plain read, because of TSO (Total Store Ordering) implemented. But on a more relaxed architecture, like ARM, you get the problem. Follow JMM formally to be sure your code is really thread-safe and doesn't contain any data races.
Why int temp = count; wait(100); count = temp + 1; is not thread-safe? One possible flow:
First thread reads count (0), save it in temp for later, and waits, allowing second thread to run (lock released);
second thread reads count (also 0), saved in temp, and waits, eventually allowing first thread to continue;
first thread increments value from temp and saves in count (1);
but second thread still holds the old value of count (0) in temp - eventually it will run and store temp+1 (1) into count, not incrementing its new value.
very simplified, just considering 2 threads
In short: wait() releases the lock allowing other (synchronized) method to run.
Just want to know how the below codes that does the same functionality differs
Code 1:
class ReadWriteCounter {
ReadWriteLock lock = new ReentrantReadWriteLock();
private Integer count = 0;
public Integer incrementAndGetCount() {
lock.writeLock().lock();
try {
count = count + 1;
return count;
} finally {
lock.writeLock().unlock();
}
}
public Integer getCount() {
lock.readLock().lock();
try {
return count;
} finally {
lock.readLock().unlock();
}
}
}
Code 2:
class ReadWriteCounter {
private Integer count = 0;
public getCount()
{
synchronized(count){
return count;
}
}
public void setCount(Integer i)
{
synchronized(count){
count = i;
}
}
}
The purpose is to ensure that when count is modified no other threads access it for reading and while reading no other threads should should access it for writing. Which is an optimum solution and why? Also, I will be using this in a class where there are field variables which needs to edited. Please offer your suggestions.
ReentrantReadWriteLock is the best way to implement your thoughts.
synchronized would only allow one thread if two or more threads attempt to read count.
But everyone could get the value of count when they all attempt to read it.
Both your solutions work however there is a bug in the way you are implementing locking.
First the difference in the two approaches:
The ReentrantReadWriteLock is mainly used in situations wherein you have many more reads than writes typically in ratios of 10 reads : 1 write. This allows the reads to happen concurrently without blocking each other however when a write starts all reads will be blocked. So performance is the primary reason.
Bug in your approach :
The object on which you are locking should be final. In setCount() you are effectively swapping the object out and that can cause a dirty read at that time.
Also, never expose the object that you are locking on. The object you are locking should be private and final. The reason is if you happen to expose the object the caller may happen to use the returned object itself for locking, in which case you will run into contention issues with components outside this class itself.
I have a use case with many writer threads and a single reader thread. The data being written is an event counter which is being read by a display thread.
The counter only ever increases and the display is intended for humans, so the exact point-in-time value is not critical. For this purpose, I would consider a solution to be correct as long as:
The value seen by the reader thread never decreases.
Reads are eventually consistent. After a certain amount of time without any writes, all reads will return the exact value.
Assuming writers are properly synchronized with each other, is it necessary to synchronize the reader thread with the writers in order to guarantee correctness, as defined above?
A simplified example. Would this be correct, as defined above?
public class Eventual {
private static class Counter {
private int count = 0;
private Lock writeLock = new ReentrantLock();
// Unsynchronized reads
public int getCount() {
return count;
}
// Synchronized writes
public void increment() {
writeLock.lock();
try {
count++;
} finally {
writeLock.unlock();
}
}
}
public static void main(String[] args) {
List<Thread> contentiousThreads = new ArrayList<>();
final Counter sharedCounter = new Counter();
// 5 synchronized writer threads
for(int i = 0; i < 5; ++i) {
contentiousThreads.add(new Thread(new Runnable(){
#Override
public void run() {
for(int i = 0; i < 20_000; ++i) {
sharedCounter.increment();
safeSleep(1);
}
}
}));
}
// 1 unsynchronized reader thread
contentiousThreads.add(new Thread(new Runnable(){
#Override
public void run() {
for(int i = 0; i < 30; ++i) {
// This value should:
// +Never decrease
// +Reach 100,000 if we are eventually consistent.
System.out.println("Count: " + sharedCounter.getCount());
safeSleep(1000);
}
}
}));
contentiousThreads.stream().forEach(t -> t.start());
// Just cleaning up...
// For the question, assume readers/writers run indefinitely
try {
for(Thread t : contentiousThreads) {
t.join();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static void safeSleep(int ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
//Don't care about error handling for now.
}
}
}
There is no guarantee that the readers would ever see an update to the count. A simple fix is to make count volatile.
As noted in another answer, in your current example, the "Final Count" will be correct because the main thread is joining the writer threads (thus establishing a happens-before relationship). however, your reader thread is never guaranteed to see any update to the count.
JTahlborn is correct, +1 from me. I was rushing and misread the question, I was assuming wrongly that the reader thread was the main thread.
The main thread can display the final count correctly due to the happens-before relationship:
All actions in a thread happen-before any other thread successfully returns from a join on that thread.
Once the main thread has joined to all the writers then the counter's updated value is visible. However, there is no happens-before relationship forcing the reader's view to get updated, you are at the mercy of the JVM implementation. There is no promise in the JLS about values getting visible if enough time passes, it is left open to the implementation. The counter value could get cached and the reader could possibly not see any updates whatsoever.
Testing this on one platform gives no assurance of what other platforms will do, so don't think this is OK just because the test passes on your PC. How many of us develop on the same platform we deploy to?
Using volatile on the counter or using AtomicInteger would be good fixes. Using AtomicInteger would allow removing the locks from the writer thread. Using volatile without locking would be OK only in a case where there is just one writer, when two or more writers are present then ++ or += not being threadsafe will be an issue. Using an Atomic class is a better choice.
(Btw eating the InterruptedException isn't "safe", it just makes the thread unresponsive to interruption, which happens when your program asks the thread to finish early.)
im trying to write a program in which two threads are created and the output should be like 1st thread prints 1 and the next thread prints 2 ,1st thread again prints 3 and so on. im a beginner so pls help me clearly. i thought thread share the same memory so they will share the i variable and print accordingly. but in output i get like thread1: 1, thread2 : 1, thread1: 2, thread2 : 2 nd so on. pls help. here is my code
class me extends Thread
{
public int name,i;
public void run()
{
for(i=1;i<=50;i++)
{
System.out.println("Thread" + name + " : " + i);
try
{
sleep(1000);
}
catch(Exception e)
{
System.out.println("some problem");
}
}
}
}
public class he
{
public static void main(String[] args)
{
me a=new me();
me b=new me();
a.name=1;
b.name=2;
a.start();
b.start();
}
}
First off you should read this http://www.oracle.com/technetwork/java/codeconventions-135099.html.
Secondly the class member variables are not shared memory. You need to explicitly pass an object (such as the counter) to both objects, such that it becomes shared. However, this will still not be enough. The shared memory can be cached by the threads so you will have race-conditions. To solve this you will need to use a Lock or use an AtomicInteger
It seems what you want to do is:
Write all numbers from 1 to 50 to System.out
without any number being printed multiple times
with the numbers being printed in order
Have this execution be done by two concurrent threads
First, let's look at what is happening in your code: Each number is printed twice. The reason for this is that i is an instance variable of me, your Thread. So each Thread has its own i, i.e., they do not share the value.
To make the two threads share the same value, we need to pass the same value when constructing me. Now, doing so with the primitive int won't help us much, because by passing an int we are not passing a reference, hence the two threads will still work on independent memory locations.
Let us define a new class, Value which holds the integer for us: (Edit: The same could also be achieved by passing an array int[], which also holds the reference to the memory location of its content)
class Value{
int i = 1;
}
Now, main can instantiate one object of type Value and pass the reference to it to both threads. This way, they can access the same memory location.
class Me extends Thread {
final Value v;
public Me(Value v){
this.v = v;
}
public void run(){
for(; v.i < 50; v.i++){
// ...
}
public static void main(){
Value valueInstance = new Value();
Me a = new Me(valueInstance);
Me b = new Me(valueInstance);
}
}
Now i isn't printed twice each time. However, you'll notice that the behavior is still not as desired. This is because the operations are interleaved: a may read i, let's say, the value is 5. Next, b increments the value of i, and stores the new value. i is now 6. However, a did still read the old value, 5, and will print 5 again, even though b just printed 5.
To solve this, we must lock the instance v, i.e., the object of type Value. Java provides the keyword synchronized, which will hold a lock during the execution of all code inside the synchronized block. However, if you simply put synchronize in your method, you still won't get what you desire. Assuming you write:
public void run(){ synchronized(v) {
for(; v.i < 50; v.i++) {
// ...
}}
Your first thread will acquire the lock, but never release it until the entire loop has been executed (which is when i has the value 50). Hence, you must release the lock somehow when it is safe to do so. Well... the only code in your run method that does not depend on i (and hence does not need to be locking) is sleep, which luckily also is where the thread spends the most time in.
Since everything is in the loop body, a simple synchronized block won't do. We can use Semaphore to acquire a lock. So, we create a Semaphore instance in the main method, and, similar to v, pass it to both threads. We can then acquire and release the lock on the Semaphore to let both threads have the chance to get the resource, while guaranteeing safety.
Here's the code that will do the trick:
public class Me extends Thread {
public int name;
final Value v;
final Semaphore lock;
public Me(Value v, Semaphore lock) {
this.v = v;
this.lock = lock;
}
public void run() {
try {
lock.acquire();
while (v.i <= 50) {
System.out.println("Thread" + name + " : " + v.i);
v.i++;
lock.release();
sleep(100);
lock.acquire();
}
lock.release();
} catch (Exception e) {
System.out.println("some problem");
}
}
public static void main(String[] args) {
Value v = new Value();
Semaphore lock = new Semaphore(1);
Me a = new Me(v, lock);
Me b = new Me(v, lock);
a.name = 1;
b.name = 2;
a.start();
b.start();
}
static class Value {
int i = 1;
}
}
Note: Since we are acquiring the lock at the end of the loop, we must also release it after the loop, or the resource will never be freed. Also, I changed the for-loop to a while loop, because we need to update i before releasing the lock for the first time, or the other thread can again read the same value.
Check the below link for the solution. Using multiple threads we can print the numbers in ascending order
http://cooltekhie.blogspot.in/2017/06/#987628206008590221