I have a java class as below:
public class Example implements Runnable {
private int num;
...
// Getter
public int getNum(){
return this.num;
}
// Setter
public void addToNum(int amount) {
if (this.amount> 0) {
this.num += amount;
}
}
...
}
This class can be instantiated by multiple threads. Each of this instances have its own 'num', that is, I do not want 'num' variable to be shared between all them.
To each instance, multiple threads can be accessed in concurreny in order to read/write 'num' variable. So what is the best option to protect read/write operations on 'num' variable in order to they are atomic operations?
I know that in case on C# it can be done using lock(object) like below link but in java I have no idea (I am new on it):
Atomic operations on C#
You can synchronized the methods, but you might find using AtomicInteger a faster option.
private final AtomicInteger num = new AtomicInteger();
...
// Getter
public int getNum(){
return this.num.get();
}
// Setter
public void addToNum(int amount) {
if (amount > 0) {
this.num.getAndAdd(amount);
}
}
Both of these methods are lock-less and avoid exposing a lock which could be used in an unintended way.
In Java 8, the getAndAdd uses a single machine code instruction for the addition via the Unsafe class. From AtomicInteger
private volatile int value;
public final int get() {
return value;
}
public final int getAndAdd(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta);
}
public synchronized void addToNum(int amount) {
if (this.num > 0) {
this.num += amount;
}
}
here you'll find documentation for it
http://www.programcreek.com/2014/02/how-to-make-a-method-thread-safe-in-java/
You can use synchronized , read about it. You can synchronized methods.
In Java ,I doubt about using volatile variables because volatile variables can used only when one thread is writing and other reads are reading. Volatile works only when one thread is writing .
"where one thread (T1) modifies the counter, and another thread (T2) reads the counter (but never modifies it), declaring the counter variable volatile is enough to guarantee visibility for T2 of writes to the counter variable.
If, however, both T1 and T2 were incrementing the counter variable, then declaring the counter variable volatile would not have been enough. More on that later."
Link : http://tutorials.jenkov.com/java-concurrency/volatile.html#:~:text=The%20Java%20volatile%20keyword%20is%20intended%20to%20address%20variable%20visibility,read%20directly%20from%20main%20memory.
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();
...
}
}
}
public class SimulatedCAS {
private int value;
public synchronized int get() { return value; }
public synchronized int compareAndSwap(int expectedValue, int newValue)
{
int oldValue = value;
if (oldValue == expectedValue)
value = newValue;
return oldValue;
}
}
public class CasCounter
{
private SimulatedCAS value;
public int getValue()
{
return value.get();
}
public int increment()
{
int value.get();
while (v != value.compareAndSwap(v, v + 1))
{
v = value.get();
}
}
}
I refereed a Book "Java Concurrency in Practice"
a Counter must be increased by multiple threads. I tried using the compare and swap method but at the end it make used of synchronized keyword which might again result in blocking and waiting of threads. using a synchronized block provides me the same performance can anybody state. what is the difference between using compare and swap and synchronized block ? or any other way to implement compare and swap without using synchronized block.
I need to increment counter with multiple threads
The AtomicInteger class is good for that.
You can create it with final AtomicInteger i=new AtomicInteger(initial_value); Then you can call i.set(new_value) to set its value, and you can call i.get() to get its value, and most importantly for your application, you can call i.incrementAndGet() to atomically increment the value.
If N different threads all call i.incrementAndGet() at "the same time," then
Each thread is guaranteed to see a different return value, and
The final value after they're all done is guaranteed to increase by exactly N.
The AtomicInteger class has quite a few other methods as well. Most of them make useful guarantees about what happens when multiple threads access the varaible.
Real Compare and Swap does optimistic locking. It changes value and then makes a rollback if something has changed the variable simultaneously. So, if the variable is modified rarely, then CAS performs better, than synchronized.
But if the variable is modified often, then synchronized performs better, because it doesn't allow anything to mess with the variable while it is changed. And so there's no need to make an expensive rollback.
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.
Say I have the following code:
private Integer number;
private final Object numberLock = new Object();
public int get(){
synchronized(number or numberLock){
return Integer.valueOf(number);
}
}
My question is, do the following versions of the add method need to have number as volatile in the below cases:
public void add(int num){
synchronized(number)
number = number + num;
}
public void add(int num){
synchronized(numberLock)
number = number + num;
}
I understand that these are both atomic operations, but my question is, is the value of number guarennteed to be pushed out to global memory and visible to all threads without using volatile?
is the value of number guarennteed to be pushed out to global memory and visible to all threads without using volatile?
Yes. synchronization offers visibility also. Actually synchronization offers visibility and atomicity, while volatile only visibility.
You haven't synchronized get so your code is not thread-safe:
public int get(){
return Integer.valueOf(number);
}
Apart from that, synchronization will guarantee visibility as Eugene already noted.
Let say that I create an object and run it in a thread, something like this.
public class Main {
public static void main(String[] args) {
SomeClass p = new SomeClass (143);
p.start();
p.updateNumber(144);
}}
Is it possible to update the parameter passed in SomeClass with a methode updateNumber() as fallows:
# Updated
class SomeClass extends Thread {
volatile int number ;
SomeClass (int number ) {
this.number = number ;
}
public void run() {
while(true){
System.out.println(number);
}
}
public void updateNumber(int n){
number =n;
}
}
Result :
144
144
144
144
144
...
Thanks
Yes, but you need to declare number as volatile, or (preferably) use an AtomicLong instead of a long.
Declare number as volatile.
When is volatile needed ?
When multiple threads using the same
variable, each thread will have its
own copy of the local cache for that
variable. So, when it's updating the
value, it is actually updated in the
local cache not in the main variable
memory. The other thread which is
using the same variable doesn't know
anything about the values changed by
the another thread. To avoid this
problem, if you declare a variable as
volatile, then it will not be stored
in the local cache. Whenever thread
are updating the values, it is updated
to the main memory. So, other threads
can access the updated value
One other option not mentioned and which is the option you should use instead of synchronization as mentioned above is the make use of the Concurrency package introduced by Doug Lee in Java 1.5.
Use the Atomic classes, these take care of all you concurrency woes. (well to a point)
Something like this:
private AtomicInteger number = new AtomicInteger(0);
public void updateNumber(int n) {
number.getAndSet(n);
}
public int getNumber() {
return number.get();
}
Java 1.6 AtomicInteger JavaDoc
Java Concurrency in Practice
In my opinion the Java Concurrency in Practice is the best book on threading in Java
SomeClass even it is Runnable, it is just a normal class and objects of it can be accessed by any thread that has reference to it. In your example. you are not calling updateNumber() form anywhere, but if you call it after p.start(), you are acessing it from the thread that actually made the instance. If you are calling updateNumber() in run(), then you are accessing it from the thread you've just started.
The other question is: is it safe in your setup to change it form multiple threads? the answer is no. You have to declare it as volatile (let say), or synchronize if you changing it based on current value. How and what to synchronize depends on what you are actually doing with it.
You can use the keyword volatilewhen all the following criteria are met:
Writes to the variable do not depend on its current value, or you can ensure that only a single thread ever updates the value
The variable does not participate in invariants with other state variables
Locking is not required for any other reason while the variable is being accessed
Otherwise, I'd recommend using some sort of synchronization policy
class SomeClass implements Runnable {
private Integer number;
SomeClass (int number) {
this.number = Integer.valueOf(number);
}
#Override
public void run() {
while(true){
System.out.println(getNumber());
}
}
public void updateNumber(int n){
synchronized(number){
number = Integer.valueOf(n);
}
}
public int getNumber(){
synchronized(number){
return number.intValue();
}
}
}
Yes, you can just call p.updateNumber(...) but you will need to be careful of thread synchronization issues.